View.java revision 1228e2cb8350ba202836660927c194f39e074e6f
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 static java.lang.Math.max;
20
21import android.animation.AnimatorInflater;
22import android.animation.StateListAnimator;
23import android.annotation.CallSuper;
24import android.annotation.ColorInt;
25import android.annotation.DrawableRes;
26import android.annotation.FloatRange;
27import android.annotation.IdRes;
28import android.annotation.IntDef;
29import android.annotation.IntRange;
30import android.annotation.LayoutRes;
31import android.annotation.NonNull;
32import android.annotation.Nullable;
33import android.annotation.Size;
34import android.annotation.TestApi;
35import android.annotation.UiThread;
36import android.content.ClipData;
37import android.content.Context;
38import android.content.ContextWrapper;
39import android.content.Intent;
40import android.content.res.ColorStateList;
41import android.content.res.Configuration;
42import android.content.res.Resources;
43import android.content.res.TypedArray;
44import android.graphics.Bitmap;
45import android.graphics.Canvas;
46import android.graphics.Color;
47import android.graphics.Insets;
48import android.graphics.Interpolator;
49import android.graphics.LinearGradient;
50import android.graphics.Matrix;
51import android.graphics.Outline;
52import android.graphics.Paint;
53import android.graphics.PixelFormat;
54import android.graphics.Point;
55import android.graphics.PorterDuff;
56import android.graphics.PorterDuffXfermode;
57import android.graphics.Rect;
58import android.graphics.RectF;
59import android.graphics.Region;
60import android.graphics.Shader;
61import android.graphics.drawable.ColorDrawable;
62import android.graphics.drawable.Drawable;
63import android.hardware.display.DisplayManagerGlobal;
64import android.os.Build;
65import android.os.Bundle;
66import android.os.Handler;
67import android.os.IBinder;
68import android.os.Parcel;
69import android.os.Parcelable;
70import android.os.RemoteException;
71import android.os.SystemClock;
72import android.os.SystemProperties;
73import android.os.Trace;
74import android.text.TextUtils;
75import android.util.AttributeSet;
76import android.util.FloatProperty;
77import android.util.LayoutDirection;
78import android.util.Log;
79import android.util.LongSparseLongArray;
80import android.util.Pools.SynchronizedPool;
81import android.util.Property;
82import android.util.SparseArray;
83import android.util.StateSet;
84import android.util.SuperNotCalledException;
85import android.util.TypedValue;
86import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
87import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
88import android.view.AccessibilityIterators.TextSegmentIterator;
89import android.view.AccessibilityIterators.WordTextSegmentIterator;
90import android.view.ContextMenu.ContextMenuInfo;
91import android.view.accessibility.AccessibilityEvent;
92import android.view.accessibility.AccessibilityEventSource;
93import android.view.accessibility.AccessibilityManager;
94import android.view.accessibility.AccessibilityNodeInfo;
95import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
96import android.view.accessibility.AccessibilityNodeProvider;
97import android.view.animation.Animation;
98import android.view.animation.AnimationUtils;
99import android.view.animation.Transformation;
100import android.view.autofill.AutoFillManager;
101import android.view.autofill.AutoFillType;
102import android.view.autofill.AutoFillValue;
103import android.view.inputmethod.EditorInfo;
104import android.view.inputmethod.InputConnection;
105import android.view.inputmethod.InputMethodManager;
106import android.widget.Checkable;
107import android.widget.FrameLayout;
108import android.widget.ScrollBarDrawable;
109
110import com.android.internal.R;
111import com.android.internal.view.TooltipPopup;
112import com.android.internal.view.menu.MenuBuilder;
113import com.android.internal.widget.ScrollBarUtils;
114
115import com.google.android.collect.Lists;
116import com.google.android.collect.Maps;
117
118import java.lang.annotation.Retention;
119import java.lang.annotation.RetentionPolicy;
120import java.lang.ref.WeakReference;
121import java.lang.reflect.Field;
122import java.lang.reflect.InvocationTargetException;
123import java.lang.reflect.Method;
124import java.lang.reflect.Modifier;
125import java.util.ArrayList;
126import java.util.Arrays;
127import java.util.Collection;
128import java.util.Collections;
129import java.util.HashMap;
130import java.util.List;
131import java.util.Locale;
132import java.util.Map;
133import java.util.concurrent.CopyOnWriteArrayList;
134import java.util.concurrent.atomic.AtomicInteger;
135import java.util.function.Predicate;
136
137/**
138 * <p>
139 * This class represents the basic building block for user interface components. A View
140 * occupies a rectangular area on the screen and is responsible for drawing and
141 * event handling. View is the base class for <em>widgets</em>, which are
142 * used to create interactive UI components (buttons, text fields, etc.). The
143 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
144 * are invisible containers that hold other Views (or other ViewGroups) and define
145 * their layout properties.
146 * </p>
147 *
148 * <div class="special reference">
149 * <h3>Developer Guides</h3>
150 * <p>For information about using this class to develop your application's user interface,
151 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
152 * </div>
153 *
154 * <a name="Using"></a>
155 * <h3>Using Views</h3>
156 * <p>
157 * All of the views in a window are arranged in a single tree. You can add views
158 * either from code or by specifying a tree of views in one or more XML layout
159 * files. There are many specialized subclasses of views that act as controls or
160 * are capable of displaying text, images, or other content.
161 * </p>
162 * <p>
163 * Once you have created a tree of views, there are typically a few types of
164 * common operations you may wish to perform:
165 * <ul>
166 * <li><strong>Set properties:</strong> for example setting the text of a
167 * {@link android.widget.TextView}. The available properties and the methods
168 * that set them will vary among the different subclasses of views. Note that
169 * properties that are known at build time can be set in the XML layout
170 * files.</li>
171 * <li><strong>Set focus:</strong> The framework will handle moving focus in
172 * response to user input. To force focus to a specific view, call
173 * {@link #requestFocus}.</li>
174 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
175 * that will be notified when something interesting happens to the view. For
176 * example, all views will let you set a listener to be notified when the view
177 * gains or loses focus. You can register such a listener using
178 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
179 * Other view subclasses offer more specialized listeners. For example, a Button
180 * exposes a listener to notify clients when the button is clicked.</li>
181 * <li><strong>Set visibility:</strong> You can hide or show views using
182 * {@link #setVisibility(int)}.</li>
183 * </ul>
184 * </p>
185 * <p><em>
186 * Note: The Android framework is responsible for measuring, laying out and
187 * drawing views. You should not call methods that perform these actions on
188 * views yourself unless you are actually implementing a
189 * {@link android.view.ViewGroup}.
190 * </em></p>
191 *
192 * <a name="Lifecycle"></a>
193 * <h3>Implementing a Custom View</h3>
194 *
195 * <p>
196 * To implement a custom view, you will usually begin by providing overrides for
197 * some of the standard methods that the framework calls on all views. You do
198 * not need to override all of these methods. In fact, you can start by just
199 * overriding {@link #onDraw(android.graphics.Canvas)}.
200 * <table border="2" width="85%" align="center" cellpadding="5">
201 *     <thead>
202 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
203 *     </thead>
204 *
205 *     <tbody>
206 *     <tr>
207 *         <td rowspan="2">Creation</td>
208 *         <td>Constructors</td>
209 *         <td>There is a form of the constructor that are called when the view
210 *         is created from code and a form that is called when the view is
211 *         inflated from a layout file. The second form should parse and apply
212 *         any attributes defined in the layout file.
213 *         </td>
214 *     </tr>
215 *     <tr>
216 *         <td><code>{@link #onFinishInflate()}</code></td>
217 *         <td>Called after a view and all of its children has been inflated
218 *         from XML.</td>
219 *     </tr>
220 *
221 *     <tr>
222 *         <td rowspan="3">Layout</td>
223 *         <td><code>{@link #onMeasure(int, int)}</code></td>
224 *         <td>Called to determine the size requirements for this view and all
225 *         of its children.
226 *         </td>
227 *     </tr>
228 *     <tr>
229 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
230 *         <td>Called when this view should assign a size and position to all
231 *         of its children.
232 *         </td>
233 *     </tr>
234 *     <tr>
235 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
236 *         <td>Called when the size of this view has changed.
237 *         </td>
238 *     </tr>
239 *
240 *     <tr>
241 *         <td>Drawing</td>
242 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
243 *         <td>Called when the view should render its content.
244 *         </td>
245 *     </tr>
246 *
247 *     <tr>
248 *         <td rowspan="4">Event processing</td>
249 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
250 *         <td>Called when a new hardware key event occurs.
251 *         </td>
252 *     </tr>
253 *     <tr>
254 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
255 *         <td>Called when a hardware key up event occurs.
256 *         </td>
257 *     </tr>
258 *     <tr>
259 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
260 *         <td>Called when a trackball motion event occurs.
261 *         </td>
262 *     </tr>
263 *     <tr>
264 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
265 *         <td>Called when a touch screen motion event occurs.
266 *         </td>
267 *     </tr>
268 *
269 *     <tr>
270 *         <td rowspan="2">Focus</td>
271 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
272 *         <td>Called when the view gains or loses focus.
273 *         </td>
274 *     </tr>
275 *
276 *     <tr>
277 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
278 *         <td>Called when the window containing the view gains or loses focus.
279 *         </td>
280 *     </tr>
281 *
282 *     <tr>
283 *         <td rowspan="3">Attaching</td>
284 *         <td><code>{@link #onAttachedToWindow()}</code></td>
285 *         <td>Called when the view is attached to a window.
286 *         </td>
287 *     </tr>
288 *
289 *     <tr>
290 *         <td><code>{@link #onDetachedFromWindow}</code></td>
291 *         <td>Called when the view is detached from its window.
292 *         </td>
293 *     </tr>
294 *
295 *     <tr>
296 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
297 *         <td>Called when the visibility of the window containing the view
298 *         has changed.
299 *         </td>
300 *     </tr>
301 *     </tbody>
302 *
303 * </table>
304 * </p>
305 *
306 * <a name="IDs"></a>
307 * <h3>IDs</h3>
308 * Views may have an integer id associated with them. These ids are typically
309 * assigned in the layout XML files, and are used to find specific views within
310 * the view tree. A common pattern is to:
311 * <ul>
312 * <li>Define a Button in the layout file and assign it a unique ID.
313 * <pre>
314 * &lt;Button
315 *     android:id="@+id/my_button"
316 *     android:layout_width="wrap_content"
317 *     android:layout_height="wrap_content"
318 *     android:text="@string/my_button_text"/&gt;
319 * </pre></li>
320 * <li>From the onCreate method of an Activity, find the Button
321 * <pre class="prettyprint">
322 *      Button myButton = (Button) findViewById(R.id.my_button);
323 * </pre></li>
324 * </ul>
325 * <p>
326 * View IDs need not be unique throughout the tree, but it is good practice to
327 * ensure that they are at least unique within the part of the tree you are
328 * searching.
329 * </p>
330 *
331 * <a name="Position"></a>
332 * <h3>Position</h3>
333 * <p>
334 * The geometry of a view is that of a rectangle. A view has a location,
335 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
336 * two dimensions, expressed as a width and a height. The unit for location
337 * and dimensions is the pixel.
338 * </p>
339 *
340 * <p>
341 * It is possible to retrieve the location of a view by invoking the methods
342 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
343 * coordinate of the rectangle representing the view. The latter returns the
344 * top, or Y, coordinate of the rectangle representing the view. These methods
345 * both return the location of the view relative to its parent. For instance,
346 * when getLeft() returns 20, that means the view is located 20 pixels to the
347 * right of the left edge of its direct parent.
348 * </p>
349 *
350 * <p>
351 * In addition, several convenience methods are offered to avoid unnecessary
352 * computations, namely {@link #getRight()} and {@link #getBottom()}.
353 * These methods return the coordinates of the right and bottom edges of the
354 * rectangle representing the view. For instance, calling {@link #getRight()}
355 * is similar to the following computation: <code>getLeft() + getWidth()</code>
356 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
357 * </p>
358 *
359 * <a name="SizePaddingMargins"></a>
360 * <h3>Size, padding and margins</h3>
361 * <p>
362 * The size of a view is expressed with a width and a height. A view actually
363 * possess two pairs of width and height values.
364 * </p>
365 *
366 * <p>
367 * The first pair is known as <em>measured width</em> and
368 * <em>measured height</em>. These dimensions define how big a view wants to be
369 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
370 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
371 * and {@link #getMeasuredHeight()}.
372 * </p>
373 *
374 * <p>
375 * The second pair is simply known as <em>width</em> and <em>height</em>, or
376 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
377 * dimensions define the actual size of the view on screen, at drawing time and
378 * after layout. These values may, but do not have to, be different from the
379 * measured width and height. The width and height can be obtained by calling
380 * {@link #getWidth()} and {@link #getHeight()}.
381 * </p>
382 *
383 * <p>
384 * To measure its dimensions, a view takes into account its padding. The padding
385 * is expressed in pixels for the left, top, right and bottom parts of the view.
386 * Padding can be used to offset the content of the view by a specific amount of
387 * pixels. For instance, a left padding of 2 will push the view's content by
388 * 2 pixels to the right of the left edge. Padding can be set using the
389 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
390 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
391 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
392 * {@link #getPaddingEnd()}.
393 * </p>
394 *
395 * <p>
396 * Even though a view can define a padding, it does not provide any support for
397 * margins. However, view groups provide such a support. Refer to
398 * {@link android.view.ViewGroup} and
399 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
400 * </p>
401 *
402 * <a name="Layout"></a>
403 * <h3>Layout</h3>
404 * <p>
405 * Layout is a two pass process: a measure pass and a layout pass. The measuring
406 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
407 * of the view tree. Each view pushes dimension specifications down the tree
408 * during the recursion. At the end of the measure pass, every view has stored
409 * its measurements. The second pass happens in
410 * {@link #layout(int,int,int,int)} and is also top-down. During
411 * this pass each parent is responsible for positioning all of its children
412 * using the sizes computed in the measure pass.
413 * </p>
414 *
415 * <p>
416 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
417 * {@link #getMeasuredHeight()} values must be set, along with those for all of
418 * that view's descendants. A view's measured width and measured height values
419 * must respect the constraints imposed by the view's parents. This guarantees
420 * that at the end of the measure pass, all parents accept all of their
421 * children's measurements. A parent view may call measure() more than once on
422 * its children. For example, the parent may measure each child once with
423 * unspecified dimensions to find out how big they want to be, then call
424 * measure() on them again with actual numbers if the sum of all the children's
425 * unconstrained sizes is too big or too small.
426 * </p>
427 *
428 * <p>
429 * The measure pass uses two classes to communicate dimensions. The
430 * {@link MeasureSpec} class is used by views to tell their parents how they
431 * want to be measured and positioned. The base LayoutParams class just
432 * describes how big the view wants to be for both width and height. For each
433 * dimension, it can specify one of:
434 * <ul>
435 * <li> an exact number
436 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
437 * (minus padding)
438 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
439 * enclose its content (plus padding).
440 * </ul>
441 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
442 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
443 * an X and Y value.
444 * </p>
445 *
446 * <p>
447 * MeasureSpecs are used to push requirements down the tree from parent to
448 * child. A MeasureSpec can be in one of three modes:
449 * <ul>
450 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
451 * of a child view. For example, a LinearLayout may call measure() on its child
452 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
453 * tall the child view wants to be given a width of 240 pixels.
454 * <li>EXACTLY: This is used by the parent to impose an exact size on the
455 * child. The child must use this size, and guarantee that all of its
456 * descendants will fit within this size.
457 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
458 * child. The child must guarantee that it and all of its descendants will fit
459 * within this size.
460 * </ul>
461 * </p>
462 *
463 * <p>
464 * To initiate a layout, call {@link #requestLayout}. This method is typically
465 * called by a view on itself when it believes that is can no longer fit within
466 * its current bounds.
467 * </p>
468 *
469 * <a name="Drawing"></a>
470 * <h3>Drawing</h3>
471 * <p>
472 * Drawing is handled by walking the tree and recording the drawing commands of
473 * any View that needs to update. After this, the drawing commands of the
474 * entire tree are issued to screen, clipped to the newly damaged area.
475 * </p>
476 *
477 * <p>
478 * The tree is largely recorded and drawn in order, with parents drawn before
479 * (i.e., behind) their children, with siblings drawn in the order they appear
480 * in the tree. If you set a background drawable for a View, then the View will
481 * draw it before calling back to its <code>onDraw()</code> method. The child
482 * drawing order can be overridden with
483 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
484 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
485 * </p>
486 *
487 * <p>
488 * To force a view to draw, call {@link #invalidate()}.
489 * </p>
490 *
491 * <a name="EventHandlingThreading"></a>
492 * <h3>Event Handling and Threading</h3>
493 * <p>
494 * The basic cycle of a view is as follows:
495 * <ol>
496 * <li>An event comes in and is dispatched to the appropriate view. The view
497 * handles the event and notifies any listeners.</li>
498 * <li>If in the course of processing the event, the view's bounds may need
499 * to be changed, the view will call {@link #requestLayout()}.</li>
500 * <li>Similarly, if in the course of processing the event the view's appearance
501 * may need to be changed, the view will call {@link #invalidate()}.</li>
502 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
503 * the framework will take care of measuring, laying out, and drawing the tree
504 * as appropriate.</li>
505 * </ol>
506 * </p>
507 *
508 * <p><em>Note: The entire view tree is single threaded. You must always be on
509 * the UI thread when calling any method on any view.</em>
510 * If you are doing work on other threads and want to update the state of a view
511 * from that thread, you should use a {@link Handler}.
512 * </p>
513 *
514 * <a name="FocusHandling"></a>
515 * <h3>Focus Handling</h3>
516 * <p>
517 * The framework will handle routine focus movement in response to user input.
518 * This includes changing the focus as views are removed or hidden, or as new
519 * views become available. Views indicate their willingness to take focus
520 * through the {@link #isFocusable} method. To change whether a view can take
521 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
522 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
523 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
524 * </p>
525 * <p>
526 * Focus movement is based on an algorithm which finds the nearest neighbor in a
527 * given direction. In rare cases, the default algorithm may not match the
528 * intended behavior of the developer. In these situations, you can provide
529 * explicit overrides by using these XML attributes in the layout file:
530 * <pre>
531 * nextFocusDown
532 * nextFocusLeft
533 * nextFocusRight
534 * nextFocusUp
535 * </pre>
536 * </p>
537 *
538 *
539 * <p>
540 * To get a particular view to take focus, call {@link #requestFocus()}.
541 * </p>
542 *
543 * <a name="TouchMode"></a>
544 * <h3>Touch Mode</h3>
545 * <p>
546 * When a user is navigating a user interface via directional keys such as a D-pad, it is
547 * necessary to give focus to actionable items such as buttons so the user can see
548 * what will take input.  If the device has touch capabilities, however, and the user
549 * begins interacting with the interface by touching it, it is no longer necessary to
550 * always highlight, or give focus to, a particular view.  This motivates a mode
551 * for interaction named 'touch mode'.
552 * </p>
553 * <p>
554 * For a touch capable device, once the user touches the screen, the device
555 * will enter touch mode.  From this point onward, only views for which
556 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
557 * Other views that are touchable, like buttons, will not take focus when touched; they will
558 * only fire the on click listeners.
559 * </p>
560 * <p>
561 * Any time a user hits a directional key, such as a D-pad direction, the view device will
562 * exit touch mode, and find a view to take focus, so that the user may resume interacting
563 * with the user interface without touching the screen again.
564 * </p>
565 * <p>
566 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
567 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
568 * </p>
569 *
570 * <a name="Scrolling"></a>
571 * <h3>Scrolling</h3>
572 * <p>
573 * The framework provides basic support for views that wish to internally
574 * scroll their content. This includes keeping track of the X and Y scroll
575 * offset as well as mechanisms for drawing scrollbars. See
576 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
577 * {@link #awakenScrollBars()} for more details.
578 * </p>
579 *
580 * <a name="Tags"></a>
581 * <h3>Tags</h3>
582 * <p>
583 * Unlike IDs, tags are not used to identify views. Tags are essentially an
584 * extra piece of information that can be associated with a view. They are most
585 * often used as a convenience to store data related to views in the views
586 * themselves rather than by putting them in a separate structure.
587 * </p>
588 * <p>
589 * Tags may be specified with character sequence values in layout XML as either
590 * a single tag using the {@link android.R.styleable#View_tag android:tag}
591 * attribute or multiple tags using the {@code <tag>} child element:
592 * <pre>
593 *     &ltView ...
594 *           android:tag="@string/mytag_value" /&gt;
595 *     &ltView ...&gt;
596 *         &lttag android:id="@+id/mytag"
597 *              android:value="@string/mytag_value" /&gt;
598 *     &lt/View>
599 * </pre>
600 * </p>
601 * <p>
602 * Tags may also be specified with arbitrary objects from code using
603 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
604 * </p>
605 *
606 * <a name="Themes"></a>
607 * <h3>Themes</h3>
608 * <p>
609 * By default, Views are created using the theme of the Context object supplied
610 * to their constructor; however, a different theme may be specified by using
611 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
612 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
613 * code.
614 * </p>
615 * <p>
616 * When the {@link android.R.styleable#View_theme android:theme} attribute is
617 * used in XML, the specified theme is applied on top of the inflation
618 * context's theme (see {@link LayoutInflater}) and used for the view itself as
619 * well as any child elements.
620 * </p>
621 * <p>
622 * In the following example, both views will be created using the Material dark
623 * color scheme; however, because an overlay theme is used which only defines a
624 * subset of attributes, the value of
625 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
626 * the inflation context's theme (e.g. the Activity theme) will be preserved.
627 * <pre>
628 *     &ltLinearLayout
629 *             ...
630 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
631 *         &ltView ...&gt;
632 *     &lt/LinearLayout&gt;
633 * </pre>
634 * </p>
635 *
636 * <a name="Properties"></a>
637 * <h3>Properties</h3>
638 * <p>
639 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
640 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
641 * available both in the {@link Property} form as well as in similarly-named setter/getter
642 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
643 * be used to set persistent state associated with these rendering-related properties on the view.
644 * The properties and methods can also be used in conjunction with
645 * {@link android.animation.Animator Animator}-based animations, described more in the
646 * <a href="#Animation">Animation</a> section.
647 * </p>
648 *
649 * <a name="Animation"></a>
650 * <h3>Animation</h3>
651 * <p>
652 * Starting with Android 3.0, the preferred way of animating views is to use the
653 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
654 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
655 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
656 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
657 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
658 * makes animating these View properties particularly easy and efficient.
659 * </p>
660 * <p>
661 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
662 * You can attach an {@link Animation} object to a view using
663 * {@link #setAnimation(Animation)} or
664 * {@link #startAnimation(Animation)}. The animation can alter the scale,
665 * rotation, translation and alpha of a view over time. If the animation is
666 * attached to a view that has children, the animation will affect the entire
667 * subtree rooted by that node. When an animation is started, the framework will
668 * take care of redrawing the appropriate views until the animation completes.
669 * </p>
670 *
671 * <a name="Security"></a>
672 * <h3>Security</h3>
673 * <p>
674 * Sometimes it is essential that an application be able to verify that an action
675 * is being performed with the full knowledge and consent of the user, such as
676 * granting a permission request, making a purchase or clicking on an advertisement.
677 * Unfortunately, a malicious application could try to spoof the user into
678 * performing these actions, unaware, by concealing the intended purpose of the view.
679 * As a remedy, the framework offers a touch filtering mechanism that can be used to
680 * improve the security of views that provide access to sensitive functionality.
681 * </p><p>
682 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
683 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
684 * will discard touches that are received whenever the view's window is obscured by
685 * another visible window.  As a result, the view will not receive touches whenever a
686 * toast, dialog or other window appears above the view's window.
687 * </p><p>
688 * For more fine-grained control over security, consider overriding the
689 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
690 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
691 * </p>
692 *
693 * @attr ref android.R.styleable#View_alpha
694 * @attr ref android.R.styleable#View_background
695 * @attr ref android.R.styleable#View_clickable
696 * @attr ref android.R.styleable#View_contentDescription
697 * @attr ref android.R.styleable#View_drawingCacheQuality
698 * @attr ref android.R.styleable#View_duplicateParentState
699 * @attr ref android.R.styleable#View_id
700 * @attr ref android.R.styleable#View_requiresFadingEdge
701 * @attr ref android.R.styleable#View_fadeScrollbars
702 * @attr ref android.R.styleable#View_fadingEdgeLength
703 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
704 * @attr ref android.R.styleable#View_fitsSystemWindows
705 * @attr ref android.R.styleable#View_isScrollContainer
706 * @attr ref android.R.styleable#View_focusable
707 * @attr ref android.R.styleable#View_focusableInTouchMode
708 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
709 * @attr ref android.R.styleable#View_keepScreenOn
710 * @attr ref android.R.styleable#View_layerType
711 * @attr ref android.R.styleable#View_layoutDirection
712 * @attr ref android.R.styleable#View_longClickable
713 * @attr ref android.R.styleable#View_minHeight
714 * @attr ref android.R.styleable#View_minWidth
715 * @attr ref android.R.styleable#View_nextFocusDown
716 * @attr ref android.R.styleable#View_nextFocusLeft
717 * @attr ref android.R.styleable#View_nextFocusRight
718 * @attr ref android.R.styleable#View_nextFocusUp
719 * @attr ref android.R.styleable#View_onClick
720 * @attr ref android.R.styleable#View_padding
721 * @attr ref android.R.styleable#View_paddingBottom
722 * @attr ref android.R.styleable#View_paddingLeft
723 * @attr ref android.R.styleable#View_paddingRight
724 * @attr ref android.R.styleable#View_paddingTop
725 * @attr ref android.R.styleable#View_paddingStart
726 * @attr ref android.R.styleable#View_paddingEnd
727 * @attr ref android.R.styleable#View_saveEnabled
728 * @attr ref android.R.styleable#View_rotation
729 * @attr ref android.R.styleable#View_rotationX
730 * @attr ref android.R.styleable#View_rotationY
731 * @attr ref android.R.styleable#View_scaleX
732 * @attr ref android.R.styleable#View_scaleY
733 * @attr ref android.R.styleable#View_scrollX
734 * @attr ref android.R.styleable#View_scrollY
735 * @attr ref android.R.styleable#View_scrollbarSize
736 * @attr ref android.R.styleable#View_scrollbarStyle
737 * @attr ref android.R.styleable#View_scrollbars
738 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
739 * @attr ref android.R.styleable#View_scrollbarFadeDuration
740 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
741 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
742 * @attr ref android.R.styleable#View_scrollbarThumbVertical
743 * @attr ref android.R.styleable#View_scrollbarTrackVertical
744 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
745 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
746 * @attr ref android.R.styleable#View_stateListAnimator
747 * @attr ref android.R.styleable#View_transitionName
748 * @attr ref android.R.styleable#View_soundEffectsEnabled
749 * @attr ref android.R.styleable#View_tag
750 * @attr ref android.R.styleable#View_textAlignment
751 * @attr ref android.R.styleable#View_textDirection
752 * @attr ref android.R.styleable#View_transformPivotX
753 * @attr ref android.R.styleable#View_transformPivotY
754 * @attr ref android.R.styleable#View_translationX
755 * @attr ref android.R.styleable#View_translationY
756 * @attr ref android.R.styleable#View_translationZ
757 * @attr ref android.R.styleable#View_visibility
758 * @attr ref android.R.styleable#View_theme
759 *
760 * @see android.view.ViewGroup
761 */
762@UiThread
763public class View implements Drawable.Callback, KeyEvent.Callback,
764        AccessibilityEventSource {
765    private static final boolean DBG = false;
766
767    /** @hide */
768    public static boolean DEBUG_DRAW = false;
769
770    /**
771     * The logging tag used by this class with android.util.Log.
772     */
773    protected static final String VIEW_LOG_TAG = "View";
774
775    /**
776     * When set to true, apps will draw debugging information about their layouts.
777     *
778     * @hide
779     */
780    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
781
782    /**
783     * When set to true, this view will save its attribute data.
784     *
785     * @hide
786     */
787    public static boolean mDebugViewAttributes = false;
788
789    /**
790     * Used to mark a View that has no ID.
791     */
792    public static final int NO_ID = -1;
793
794    /**
795     * Signals that compatibility booleans have been initialized according to
796     * target SDK versions.
797     */
798    private static boolean sCompatibilityDone = false;
799
800    /**
801     * Use the old (broken) way of building MeasureSpecs.
802     */
803    private static boolean sUseBrokenMakeMeasureSpec = false;
804
805    /**
806     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
807     */
808    static boolean sUseZeroUnspecifiedMeasureSpec = false;
809
810    /**
811     * Ignore any optimizations using the measure cache.
812     */
813    private static boolean sIgnoreMeasureCache = false;
814
815    /**
816     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
817     */
818    private static boolean sAlwaysRemeasureExactly = false;
819
820    /**
821     * Relax constraints around whether setLayoutParams() must be called after
822     * modifying the layout params.
823     */
824    private static boolean sLayoutParamsAlwaysChanged = false;
825
826    /**
827     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
828     * without throwing
829     */
830    static boolean sTextureViewIgnoresDrawableSetters = false;
831
832    /**
833     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
834     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
835     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
836     * check is implemented for backwards compatibility.
837     *
838     * {@hide}
839     */
840    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
841
842    /**
843     * Prior to N, when drag enters into child of a view that has already received an
844     * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
845     * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
846     * false from its event handler for these events.
847     * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
848     * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
849     * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
850     */
851    static boolean sCascadedDragDrop;
852
853    /**
854     * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
855     * to determine things like whether or not to permit item click events. We can't break
856     * apps that do this just because more things (clickable things) are now auto-focusable
857     * and they would get different results, so give old behavior to old apps.
858     */
859    static boolean sHasFocusableExcludeAutoFocusable;
860
861    /**
862     * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
863     * made focusable by default. As a result, apps could (incorrectly) change the clickable
864     * setting of views off the UI thread. Now that clickable can effect the focusable state,
865     * changing the clickable attribute off the UI thread will cause an exception (since changing
866     * the focusable state checks). In order to prevent apps from crashing, we will handle this
867     * specific case and just not notify parents on new focusables resulting from marking views
868     * clickable from outside the UI thread.
869     */
870    private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
871
872    /** @hide */
873    @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
874    @Retention(RetentionPolicy.SOURCE)
875    public @interface Focusable {}
876
877    /**
878     * This view does not want keystrokes.
879     * <p>
880     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
881     * android:focusable}.
882     */
883    public static final int NOT_FOCUSABLE = 0x00000000;
884
885    /**
886     * This view wants keystrokes.
887     * <p>
888     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
889     * android:focusable}.
890     */
891    public static final int FOCUSABLE = 0x00000001;
892
893    /**
894     * This view determines focusability automatically. This is the default.
895     * <p>
896     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
897     * android:focusable}.
898     */
899    public static final int FOCUSABLE_AUTO = 0x00000010;
900
901    /**
902     * Mask for use with setFlags indicating bits used for focus.
903     */
904    private static final int FOCUSABLE_MASK = 0x00000011;
905
906    /**
907     * This view will adjust its padding to fit sytem windows (e.g. status bar)
908     */
909    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
910
911    /** @hide */
912    @IntDef({VISIBLE, INVISIBLE, GONE})
913    @Retention(RetentionPolicy.SOURCE)
914    public @interface Visibility {}
915
916    /**
917     * This view is visible.
918     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
919     * android:visibility}.
920     */
921    public static final int VISIBLE = 0x00000000;
922
923    /**
924     * This view is invisible, but it still takes up space for layout purposes.
925     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
926     * android:visibility}.
927     */
928    public static final int INVISIBLE = 0x00000004;
929
930    /**
931     * This view is invisible, and it doesn't take any space for layout
932     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
933     * android:visibility}.
934     */
935    public static final int GONE = 0x00000008;
936
937    /**
938     * Mask for use with setFlags indicating bits used for visibility.
939     * {@hide}
940     */
941    static final int VISIBILITY_MASK = 0x0000000C;
942
943    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
944
945    /**
946     * This view is enabled. Interpretation varies by subclass.
947     * Use with ENABLED_MASK when calling setFlags.
948     * {@hide}
949     */
950    static final int ENABLED = 0x00000000;
951
952    /**
953     * This view is disabled. Interpretation varies by subclass.
954     * Use with ENABLED_MASK when calling setFlags.
955     * {@hide}
956     */
957    static final int DISABLED = 0x00000020;
958
959   /**
960    * Mask for use with setFlags indicating bits used for indicating whether
961    * this view is enabled
962    * {@hide}
963    */
964    static final int ENABLED_MASK = 0x00000020;
965
966    /**
967     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
968     * called and further optimizations will be performed. It is okay to have
969     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
970     * {@hide}
971     */
972    static final int WILL_NOT_DRAW = 0x00000080;
973
974    /**
975     * Mask for use with setFlags indicating bits used for indicating whether
976     * this view is will draw
977     * {@hide}
978     */
979    static final int DRAW_MASK = 0x00000080;
980
981    /**
982     * <p>This view doesn't show scrollbars.</p>
983     * {@hide}
984     */
985    static final int SCROLLBARS_NONE = 0x00000000;
986
987    /**
988     * <p>This view shows horizontal scrollbars.</p>
989     * {@hide}
990     */
991    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
992
993    /**
994     * <p>This view shows vertical scrollbars.</p>
995     * {@hide}
996     */
997    static final int SCROLLBARS_VERTICAL = 0x00000200;
998
999    /**
1000     * <p>Mask for use with setFlags indicating bits used for indicating which
1001     * scrollbars are enabled.</p>
1002     * {@hide}
1003     */
1004    static final int SCROLLBARS_MASK = 0x00000300;
1005
1006    /**
1007     * Indicates that the view should filter touches when its window is obscured.
1008     * Refer to the class comments for more information about this security feature.
1009     * {@hide}
1010     */
1011    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1012
1013    /**
1014     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1015     * that they are optional and should be skipped if the window has
1016     * requested system UI flags that ignore those insets for layout.
1017     */
1018    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1019
1020    /**
1021     * <p>This view doesn't show fading edges.</p>
1022     * {@hide}
1023     */
1024    static final int FADING_EDGE_NONE = 0x00000000;
1025
1026    /**
1027     * <p>This view shows horizontal fading edges.</p>
1028     * {@hide}
1029     */
1030    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1031
1032    /**
1033     * <p>This view shows vertical fading edges.</p>
1034     * {@hide}
1035     */
1036    static final int FADING_EDGE_VERTICAL = 0x00002000;
1037
1038    /**
1039     * <p>Mask for use with setFlags indicating bits used for indicating which
1040     * fading edges are enabled.</p>
1041     * {@hide}
1042     */
1043    static final int FADING_EDGE_MASK = 0x00003000;
1044
1045    /**
1046     * <p>Indicates this view can be clicked. When clickable, a View reacts
1047     * to clicks by notifying the OnClickListener.<p>
1048     * {@hide}
1049     */
1050    static final int CLICKABLE = 0x00004000;
1051
1052    /**
1053     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1054     * {@hide}
1055     */
1056    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1057
1058    /**
1059     * <p>Indicates that no icicle should be saved for this view.<p>
1060     * {@hide}
1061     */
1062    static final int SAVE_DISABLED = 0x000010000;
1063
1064    /**
1065     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1066     * property.</p>
1067     * {@hide}
1068     */
1069    static final int SAVE_DISABLED_MASK = 0x000010000;
1070
1071    /**
1072     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1073     * {@hide}
1074     */
1075    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1076
1077    /**
1078     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1079     * {@hide}
1080     */
1081    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1082
1083    /** @hide */
1084    @Retention(RetentionPolicy.SOURCE)
1085    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1086    public @interface DrawingCacheQuality {}
1087
1088    /**
1089     * <p>Enables low quality mode for the drawing cache.</p>
1090     */
1091    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1092
1093    /**
1094     * <p>Enables high quality mode for the drawing cache.</p>
1095     */
1096    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1097
1098    /**
1099     * <p>Enables automatic quality mode for the drawing cache.</p>
1100     */
1101    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1102
1103    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1104            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1105    };
1106
1107    /**
1108     * <p>Mask for use with setFlags indicating bits used for the cache
1109     * quality property.</p>
1110     * {@hide}
1111     */
1112    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1113
1114    /**
1115     * <p>
1116     * Indicates this view can be long clicked. When long clickable, a View
1117     * reacts to long clicks by notifying the OnLongClickListener or showing a
1118     * context menu.
1119     * </p>
1120     * {@hide}
1121     */
1122    static final int LONG_CLICKABLE = 0x00200000;
1123
1124    /**
1125     * <p>Indicates that this view gets its drawable states from its direct parent
1126     * and ignores its original internal states.</p>
1127     *
1128     * @hide
1129     */
1130    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1131
1132    /**
1133     * <p>
1134     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1135     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1136     * OnContextClickListener.
1137     * </p>
1138     * {@hide}
1139     */
1140    static final int CONTEXT_CLICKABLE = 0x00800000;
1141
1142
1143    /** @hide */
1144    @IntDef({
1145        SCROLLBARS_INSIDE_OVERLAY,
1146        SCROLLBARS_INSIDE_INSET,
1147        SCROLLBARS_OUTSIDE_OVERLAY,
1148        SCROLLBARS_OUTSIDE_INSET
1149    })
1150    @Retention(RetentionPolicy.SOURCE)
1151    public @interface ScrollBarStyle {}
1152
1153    /**
1154     * The scrollbar style to display the scrollbars inside the content area,
1155     * without increasing the padding. The scrollbars will be overlaid with
1156     * translucency on the view's content.
1157     */
1158    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1159
1160    /**
1161     * The scrollbar style to display the scrollbars inside the padded area,
1162     * increasing the padding of the view. The scrollbars will not overlap the
1163     * content area of the view.
1164     */
1165    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1166
1167    /**
1168     * The scrollbar style to display the scrollbars at the edge of the view,
1169     * without increasing the padding. The scrollbars will be overlaid with
1170     * translucency.
1171     */
1172    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1173
1174    /**
1175     * The scrollbar style to display the scrollbars at the edge of the view,
1176     * increasing the padding of the view. The scrollbars will only overlap the
1177     * background, if any.
1178     */
1179    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1180
1181    /**
1182     * Mask to check if the scrollbar style is overlay or inset.
1183     * {@hide}
1184     */
1185    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1186
1187    /**
1188     * Mask to check if the scrollbar style is inside or outside.
1189     * {@hide}
1190     */
1191    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1192
1193    /**
1194     * Mask for scrollbar style.
1195     * {@hide}
1196     */
1197    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1198
1199    /**
1200     * View flag indicating that the screen should remain on while the
1201     * window containing this view is visible to the user.  This effectively
1202     * takes care of automatically setting the WindowManager's
1203     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1204     */
1205    public static final int KEEP_SCREEN_ON = 0x04000000;
1206
1207    /**
1208     * View flag indicating whether this view should have sound effects enabled
1209     * for events such as clicking and touching.
1210     */
1211    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1212
1213    /**
1214     * View flag indicating whether this view should have haptic feedback
1215     * enabled for events such as long presses.
1216     */
1217    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1218
1219    /**
1220     * <p>Indicates that the view hierarchy should stop saving state when
1221     * it reaches this view.  If state saving is initiated immediately at
1222     * the view, it will be allowed.
1223     * {@hide}
1224     */
1225    static final int PARENT_SAVE_DISABLED = 0x20000000;
1226
1227    /**
1228     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1229     * {@hide}
1230     */
1231    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1232
1233    private static Paint sDebugPaint;
1234
1235    /**
1236     * <p>Indicates this view can display a tooltip on hover or long press.</p>
1237     * {@hide}
1238     */
1239    static final int TOOLTIP = 0x40000000;
1240
1241    /** @hide */
1242    @IntDef(flag = true,
1243            value = {
1244                FOCUSABLES_ALL,
1245                FOCUSABLES_TOUCH_MODE
1246            })
1247    @Retention(RetentionPolicy.SOURCE)
1248    public @interface FocusableMode {}
1249
1250    /**
1251     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1252     * should add all focusable Views regardless if they are focusable in touch mode.
1253     */
1254    public static final int FOCUSABLES_ALL = 0x00000000;
1255
1256    /**
1257     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1258     * should add only Views focusable in touch mode.
1259     */
1260    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1261
1262    /** @hide */
1263    @IntDef({
1264            FOCUS_BACKWARD,
1265            FOCUS_FORWARD,
1266            FOCUS_LEFT,
1267            FOCUS_UP,
1268            FOCUS_RIGHT,
1269            FOCUS_DOWN
1270    })
1271    @Retention(RetentionPolicy.SOURCE)
1272    public @interface FocusDirection {}
1273
1274    /** @hide */
1275    @IntDef({
1276            FOCUS_LEFT,
1277            FOCUS_UP,
1278            FOCUS_RIGHT,
1279            FOCUS_DOWN
1280    })
1281    @Retention(RetentionPolicy.SOURCE)
1282    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1283
1284    /**
1285     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1286     * item.
1287     */
1288    public static final int FOCUS_BACKWARD = 0x00000001;
1289
1290    /**
1291     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1292     * item.
1293     */
1294    public static final int FOCUS_FORWARD = 0x00000002;
1295
1296    /**
1297     * Use with {@link #focusSearch(int)}. Move focus to the left.
1298     */
1299    public static final int FOCUS_LEFT = 0x00000011;
1300
1301    /**
1302     * Use with {@link #focusSearch(int)}. Move focus up.
1303     */
1304    public static final int FOCUS_UP = 0x00000021;
1305
1306    /**
1307     * Use with {@link #focusSearch(int)}. Move focus to the right.
1308     */
1309    public static final int FOCUS_RIGHT = 0x00000042;
1310
1311    /**
1312     * Use with {@link #focusSearch(int)}. Move focus down.
1313     */
1314    public static final int FOCUS_DOWN = 0x00000082;
1315
1316    /**
1317     * Bits of {@link #getMeasuredWidthAndState()} and
1318     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1319     */
1320    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1321
1322    /**
1323     * Bits of {@link #getMeasuredWidthAndState()} and
1324     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1325     */
1326    public static final int MEASURED_STATE_MASK = 0xff000000;
1327
1328    /**
1329     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1330     * for functions that combine both width and height into a single int,
1331     * such as {@link #getMeasuredState()} and the childState argument of
1332     * {@link #resolveSizeAndState(int, int, int)}.
1333     */
1334    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1335
1336    /**
1337     * Bit of {@link #getMeasuredWidthAndState()} and
1338     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1339     * is smaller that the space the view would like to have.
1340     */
1341    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1342
1343    /**
1344     * Base View state sets
1345     */
1346    // Singles
1347    /**
1348     * Indicates the view has no states set. States are used with
1349     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1350     * view depending on its state.
1351     *
1352     * @see android.graphics.drawable.Drawable
1353     * @see #getDrawableState()
1354     */
1355    protected static final int[] EMPTY_STATE_SET;
1356    /**
1357     * Indicates the view is enabled. States are used with
1358     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1359     * view depending on its state.
1360     *
1361     * @see android.graphics.drawable.Drawable
1362     * @see #getDrawableState()
1363     */
1364    protected static final int[] ENABLED_STATE_SET;
1365    /**
1366     * Indicates the view is focused. States are used with
1367     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1368     * view depending on its state.
1369     *
1370     * @see android.graphics.drawable.Drawable
1371     * @see #getDrawableState()
1372     */
1373    protected static final int[] FOCUSED_STATE_SET;
1374    /**
1375     * Indicates the view is selected. States are used with
1376     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1377     * view depending on its state.
1378     *
1379     * @see android.graphics.drawable.Drawable
1380     * @see #getDrawableState()
1381     */
1382    protected static final int[] SELECTED_STATE_SET;
1383    /**
1384     * Indicates the view is pressed. States are used with
1385     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1386     * view depending on its state.
1387     *
1388     * @see android.graphics.drawable.Drawable
1389     * @see #getDrawableState()
1390     */
1391    protected static final int[] PRESSED_STATE_SET;
1392    /**
1393     * Indicates the view's window has focus. States are used with
1394     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1395     * view depending on its state.
1396     *
1397     * @see android.graphics.drawable.Drawable
1398     * @see #getDrawableState()
1399     */
1400    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1401    // Doubles
1402    /**
1403     * Indicates the view is enabled and has the focus.
1404     *
1405     * @see #ENABLED_STATE_SET
1406     * @see #FOCUSED_STATE_SET
1407     */
1408    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1409    /**
1410     * Indicates the view is enabled and selected.
1411     *
1412     * @see #ENABLED_STATE_SET
1413     * @see #SELECTED_STATE_SET
1414     */
1415    protected static final int[] ENABLED_SELECTED_STATE_SET;
1416    /**
1417     * Indicates the view is enabled and that its window has focus.
1418     *
1419     * @see #ENABLED_STATE_SET
1420     * @see #WINDOW_FOCUSED_STATE_SET
1421     */
1422    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1423    /**
1424     * Indicates the view is focused and selected.
1425     *
1426     * @see #FOCUSED_STATE_SET
1427     * @see #SELECTED_STATE_SET
1428     */
1429    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1430    /**
1431     * Indicates the view has the focus and that its window has the focus.
1432     *
1433     * @see #FOCUSED_STATE_SET
1434     * @see #WINDOW_FOCUSED_STATE_SET
1435     */
1436    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1437    /**
1438     * Indicates the view is selected and that its window has the focus.
1439     *
1440     * @see #SELECTED_STATE_SET
1441     * @see #WINDOW_FOCUSED_STATE_SET
1442     */
1443    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1444    // Triples
1445    /**
1446     * Indicates the view is enabled, focused and selected.
1447     *
1448     * @see #ENABLED_STATE_SET
1449     * @see #FOCUSED_STATE_SET
1450     * @see #SELECTED_STATE_SET
1451     */
1452    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1453    /**
1454     * Indicates the view is enabled, focused and its window has the focus.
1455     *
1456     * @see #ENABLED_STATE_SET
1457     * @see #FOCUSED_STATE_SET
1458     * @see #WINDOW_FOCUSED_STATE_SET
1459     */
1460    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1461    /**
1462     * Indicates the view is enabled, selected and its window has the focus.
1463     *
1464     * @see #ENABLED_STATE_SET
1465     * @see #SELECTED_STATE_SET
1466     * @see #WINDOW_FOCUSED_STATE_SET
1467     */
1468    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1469    /**
1470     * Indicates the view is focused, selected and its window has the focus.
1471     *
1472     * @see #FOCUSED_STATE_SET
1473     * @see #SELECTED_STATE_SET
1474     * @see #WINDOW_FOCUSED_STATE_SET
1475     */
1476    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1477    /**
1478     * Indicates the view is enabled, focused, selected and its window
1479     * has the focus.
1480     *
1481     * @see #ENABLED_STATE_SET
1482     * @see #FOCUSED_STATE_SET
1483     * @see #SELECTED_STATE_SET
1484     * @see #WINDOW_FOCUSED_STATE_SET
1485     */
1486    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1487    /**
1488     * Indicates the view is pressed and its window has the focus.
1489     *
1490     * @see #PRESSED_STATE_SET
1491     * @see #WINDOW_FOCUSED_STATE_SET
1492     */
1493    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1494    /**
1495     * Indicates the view is pressed and selected.
1496     *
1497     * @see #PRESSED_STATE_SET
1498     * @see #SELECTED_STATE_SET
1499     */
1500    protected static final int[] PRESSED_SELECTED_STATE_SET;
1501    /**
1502     * Indicates the view is pressed, selected and its window has the focus.
1503     *
1504     * @see #PRESSED_STATE_SET
1505     * @see #SELECTED_STATE_SET
1506     * @see #WINDOW_FOCUSED_STATE_SET
1507     */
1508    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1509    /**
1510     * Indicates the view is pressed and focused.
1511     *
1512     * @see #PRESSED_STATE_SET
1513     * @see #FOCUSED_STATE_SET
1514     */
1515    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1516    /**
1517     * Indicates the view is pressed, focused and its window has the focus.
1518     *
1519     * @see #PRESSED_STATE_SET
1520     * @see #FOCUSED_STATE_SET
1521     * @see #WINDOW_FOCUSED_STATE_SET
1522     */
1523    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1524    /**
1525     * Indicates the view is pressed, focused and selected.
1526     *
1527     * @see #PRESSED_STATE_SET
1528     * @see #SELECTED_STATE_SET
1529     * @see #FOCUSED_STATE_SET
1530     */
1531    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1532    /**
1533     * Indicates the view is pressed, focused, selected and its window has the focus.
1534     *
1535     * @see #PRESSED_STATE_SET
1536     * @see #FOCUSED_STATE_SET
1537     * @see #SELECTED_STATE_SET
1538     * @see #WINDOW_FOCUSED_STATE_SET
1539     */
1540    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1541    /**
1542     * Indicates the view is pressed and enabled.
1543     *
1544     * @see #PRESSED_STATE_SET
1545     * @see #ENABLED_STATE_SET
1546     */
1547    protected static final int[] PRESSED_ENABLED_STATE_SET;
1548    /**
1549     * Indicates the view is pressed, enabled and its window has the focus.
1550     *
1551     * @see #PRESSED_STATE_SET
1552     * @see #ENABLED_STATE_SET
1553     * @see #WINDOW_FOCUSED_STATE_SET
1554     */
1555    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1556    /**
1557     * Indicates the view is pressed, enabled and selected.
1558     *
1559     * @see #PRESSED_STATE_SET
1560     * @see #ENABLED_STATE_SET
1561     * @see #SELECTED_STATE_SET
1562     */
1563    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1564    /**
1565     * Indicates the view is pressed, enabled, selected and its window has the
1566     * focus.
1567     *
1568     * @see #PRESSED_STATE_SET
1569     * @see #ENABLED_STATE_SET
1570     * @see #SELECTED_STATE_SET
1571     * @see #WINDOW_FOCUSED_STATE_SET
1572     */
1573    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1574    /**
1575     * Indicates the view is pressed, enabled and focused.
1576     *
1577     * @see #PRESSED_STATE_SET
1578     * @see #ENABLED_STATE_SET
1579     * @see #FOCUSED_STATE_SET
1580     */
1581    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1582    /**
1583     * Indicates the view is pressed, enabled, focused and its window has the
1584     * focus.
1585     *
1586     * @see #PRESSED_STATE_SET
1587     * @see #ENABLED_STATE_SET
1588     * @see #FOCUSED_STATE_SET
1589     * @see #WINDOW_FOCUSED_STATE_SET
1590     */
1591    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1592    /**
1593     * Indicates the view is pressed, enabled, focused and selected.
1594     *
1595     * @see #PRESSED_STATE_SET
1596     * @see #ENABLED_STATE_SET
1597     * @see #SELECTED_STATE_SET
1598     * @see #FOCUSED_STATE_SET
1599     */
1600    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1601    /**
1602     * Indicates the view is pressed, enabled, focused, selected and its window
1603     * has the focus.
1604     *
1605     * @see #PRESSED_STATE_SET
1606     * @see #ENABLED_STATE_SET
1607     * @see #SELECTED_STATE_SET
1608     * @see #FOCUSED_STATE_SET
1609     * @see #WINDOW_FOCUSED_STATE_SET
1610     */
1611    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1612
1613    static {
1614        EMPTY_STATE_SET = StateSet.get(0);
1615
1616        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1617
1618        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1619        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1620                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1621
1622        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1623        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1624                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1625        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1626                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1627        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1628                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1629                        | StateSet.VIEW_STATE_FOCUSED);
1630
1631        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1632        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1633                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1634        ENABLED_SELECTED_STATE_SET = StateSet.get(
1635                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1636        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1637                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1638                        | StateSet.VIEW_STATE_ENABLED);
1639        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1640                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1641        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1642                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1643                        | StateSet.VIEW_STATE_ENABLED);
1644        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1645                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1646                        | StateSet.VIEW_STATE_ENABLED);
1647        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1648                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1649                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1650
1651        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1652        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1653                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1654        PRESSED_SELECTED_STATE_SET = StateSet.get(
1655                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1656        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1657                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1658                        | StateSet.VIEW_STATE_PRESSED);
1659        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1660                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1661        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1662                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1663                        | StateSet.VIEW_STATE_PRESSED);
1664        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1665                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1666                        | StateSet.VIEW_STATE_PRESSED);
1667        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1668                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1669                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1670        PRESSED_ENABLED_STATE_SET = StateSet.get(
1671                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1672        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1673                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1674                        | StateSet.VIEW_STATE_PRESSED);
1675        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1676                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1677                        | StateSet.VIEW_STATE_PRESSED);
1678        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1679                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1680                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1681        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1682                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1683                        | StateSet.VIEW_STATE_PRESSED);
1684        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1685                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1686                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1687        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1688                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1689                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1690        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1691                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1692                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1693                        | StateSet.VIEW_STATE_PRESSED);
1694    }
1695
1696    /**
1697     * Accessibility event types that are dispatched for text population.
1698     */
1699    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1700            AccessibilityEvent.TYPE_VIEW_CLICKED
1701            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1702            | AccessibilityEvent.TYPE_VIEW_SELECTED
1703            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1704            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1705            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1706            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1707            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1708            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1709            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1710            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1711
1712    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
1713
1714    static final int DEBUG_CORNERS_SIZE_DIP = 8;
1715
1716    /**
1717     * Temporary Rect currently for use in setBackground().  This will probably
1718     * be extended in the future to hold our own class with more than just
1719     * a Rect. :)
1720     */
1721    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1722
1723    /**
1724     * Map used to store views' tags.
1725     */
1726    private SparseArray<Object> mKeyedTags;
1727
1728    /**
1729     * The next available accessibility id.
1730     */
1731    private static int sNextAccessibilityViewId;
1732
1733    /**
1734     * The animation currently associated with this view.
1735     * @hide
1736     */
1737    protected Animation mCurrentAnimation = null;
1738
1739    /**
1740     * Width as measured during measure pass.
1741     * {@hide}
1742     */
1743    @ViewDebug.ExportedProperty(category = "measurement")
1744    int mMeasuredWidth;
1745
1746    /**
1747     * Height as measured during measure pass.
1748     * {@hide}
1749     */
1750    @ViewDebug.ExportedProperty(category = "measurement")
1751    int mMeasuredHeight;
1752
1753    /**
1754     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1755     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1756     * its display list. This flag, used only when hw accelerated, allows us to clear the
1757     * flag while retaining this information until it's needed (at getDisplayList() time and
1758     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1759     *
1760     * {@hide}
1761     */
1762    boolean mRecreateDisplayList = false;
1763
1764    /**
1765     * The view's identifier.
1766     * {@hide}
1767     *
1768     * @see #setId(int)
1769     * @see #getId()
1770     */
1771    @IdRes
1772    @ViewDebug.ExportedProperty(resolveId = true)
1773    int mID = NO_ID;
1774
1775    /**
1776     * The stable ID of this view for accessibility purposes.
1777     */
1778    int mAccessibilityViewId = NO_ID;
1779
1780    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1781
1782    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1783
1784    /**
1785     * The view's tag.
1786     * {@hide}
1787     *
1788     * @see #setTag(Object)
1789     * @see #getTag()
1790     */
1791    protected Object mTag = null;
1792
1793    // for mPrivateFlags:
1794    /** {@hide} */
1795    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1796    /** {@hide} */
1797    static final int PFLAG_FOCUSED                     = 0x00000002;
1798    /** {@hide} */
1799    static final int PFLAG_SELECTED                    = 0x00000004;
1800    /** {@hide} */
1801    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1802    /** {@hide} */
1803    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1804    /** {@hide} */
1805    static final int PFLAG_DRAWN                       = 0x00000020;
1806    /**
1807     * When this flag is set, this view is running an animation on behalf of its
1808     * children and should therefore not cancel invalidate requests, even if they
1809     * lie outside of this view's bounds.
1810     *
1811     * {@hide}
1812     */
1813    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1814    /** {@hide} */
1815    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1816    /** {@hide} */
1817    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1818    /** {@hide} */
1819    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1820    /** {@hide} */
1821    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1822    /** {@hide} */
1823    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1824    /** {@hide} */
1825    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1826
1827    private static final int PFLAG_PRESSED             = 0x00004000;
1828
1829    /** {@hide} */
1830    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1831    /**
1832     * Flag used to indicate that this view should be drawn once more (and only once
1833     * more) after its animation has completed.
1834     * {@hide}
1835     */
1836    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1837
1838    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1839
1840    /**
1841     * Indicates that the View returned true when onSetAlpha() was called and that
1842     * the alpha must be restored.
1843     * {@hide}
1844     */
1845    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1846
1847    /**
1848     * Set by {@link #setScrollContainer(boolean)}.
1849     */
1850    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1851
1852    /**
1853     * Set by {@link #setScrollContainer(boolean)}.
1854     */
1855    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1856
1857    /**
1858     * View flag indicating whether this view was invalidated (fully or partially.)
1859     *
1860     * @hide
1861     */
1862    static final int PFLAG_DIRTY                       = 0x00200000;
1863
1864    /**
1865     * View flag indicating whether this view was invalidated by an opaque
1866     * invalidate request.
1867     *
1868     * @hide
1869     */
1870    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1871
1872    /**
1873     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1874     *
1875     * @hide
1876     */
1877    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1878
1879    /**
1880     * Indicates whether the background is opaque.
1881     *
1882     * @hide
1883     */
1884    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1885
1886    /**
1887     * Indicates whether the scrollbars are opaque.
1888     *
1889     * @hide
1890     */
1891    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1892
1893    /**
1894     * Indicates whether the view is opaque.
1895     *
1896     * @hide
1897     */
1898    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1899
1900    /**
1901     * Indicates a prepressed state;
1902     * the short time between ACTION_DOWN and recognizing
1903     * a 'real' press. Prepressed is used to recognize quick taps
1904     * even when they are shorter than ViewConfiguration.getTapTimeout().
1905     *
1906     * @hide
1907     */
1908    private static final int PFLAG_PREPRESSED          = 0x02000000;
1909
1910    /**
1911     * Indicates whether the view is temporarily detached.
1912     *
1913     * @hide
1914     */
1915    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1916
1917    /**
1918     * Indicates that we should awaken scroll bars once attached
1919     *
1920     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1921     * during window attachment and it is no longer needed. Feel free to repurpose it.
1922     *
1923     * @hide
1924     */
1925    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1926
1927    /**
1928     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1929     * @hide
1930     */
1931    private static final int PFLAG_HOVERED             = 0x10000000;
1932
1933    /**
1934     * no longer needed, should be reused
1935     */
1936    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1937
1938    /** {@hide} */
1939    static final int PFLAG_ACTIVATED                   = 0x40000000;
1940
1941    /**
1942     * Indicates that this view was specifically invalidated, not just dirtied because some
1943     * child view was invalidated. The flag is used to determine when we need to recreate
1944     * a view's display list (as opposed to just returning a reference to its existing
1945     * display list).
1946     *
1947     * @hide
1948     */
1949    static final int PFLAG_INVALIDATED                 = 0x80000000;
1950
1951    /**
1952     * Masks for mPrivateFlags2, as generated by dumpFlags():
1953     *
1954     * |-------|-------|-------|-------|
1955     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1956     *                                1  PFLAG2_DRAG_HOVERED
1957     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1958     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1959     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1960     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1961     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1962     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1963     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1964     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1965     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1966     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1967     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1968     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1969     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1970     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1971     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1972     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1973     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1974     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1975     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1976     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1977     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1978     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1979     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1980     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1981     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1982     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1983     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1984     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1985     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1986     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1987     *    1                              PFLAG2_PADDING_RESOLVED
1988     *   1                               PFLAG2_DRAWABLE_RESOLVED
1989     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1990     * |-------|-------|-------|-------|
1991     */
1992
1993    /**
1994     * Indicates that this view has reported that it can accept the current drag's content.
1995     * Cleared when the drag operation concludes.
1996     * @hide
1997     */
1998    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1999
2000    /**
2001     * Indicates that this view is currently directly under the drag location in a
2002     * drag-and-drop operation involving content that it can accept.  Cleared when
2003     * the drag exits the view, or when the drag operation concludes.
2004     * @hide
2005     */
2006    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2007
2008    /** @hide */
2009    @IntDef({
2010        LAYOUT_DIRECTION_LTR,
2011        LAYOUT_DIRECTION_RTL,
2012        LAYOUT_DIRECTION_INHERIT,
2013        LAYOUT_DIRECTION_LOCALE
2014    })
2015    @Retention(RetentionPolicy.SOURCE)
2016    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2017    public @interface LayoutDir {}
2018
2019    /** @hide */
2020    @IntDef({
2021        LAYOUT_DIRECTION_LTR,
2022        LAYOUT_DIRECTION_RTL
2023    })
2024    @Retention(RetentionPolicy.SOURCE)
2025    public @interface ResolvedLayoutDir {}
2026
2027    /**
2028     * A flag to indicate that the layout direction of this view has not been defined yet.
2029     * @hide
2030     */
2031    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2032
2033    /**
2034     * Horizontal layout direction of this view is from Left to Right.
2035     * Use with {@link #setLayoutDirection}.
2036     */
2037    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2038
2039    /**
2040     * Horizontal layout direction of this view is from Right to Left.
2041     * Use with {@link #setLayoutDirection}.
2042     */
2043    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2044
2045    /**
2046     * Horizontal layout direction of this view is inherited from its parent.
2047     * Use with {@link #setLayoutDirection}.
2048     */
2049    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2050
2051    /**
2052     * Horizontal layout direction of this view is from deduced from the default language
2053     * script for the locale. Use with {@link #setLayoutDirection}.
2054     */
2055    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2056
2057    /**
2058     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2059     * @hide
2060     */
2061    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2062
2063    /**
2064     * Mask for use with private flags indicating bits used for horizontal layout direction.
2065     * @hide
2066     */
2067    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2068
2069    /**
2070     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2071     * right-to-left direction.
2072     * @hide
2073     */
2074    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2075
2076    /**
2077     * Indicates whether the view horizontal layout direction has been resolved.
2078     * @hide
2079     */
2080    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2081
2082    /**
2083     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2084     * @hide
2085     */
2086    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2087            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2088
2089    /*
2090     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2091     * flag value.
2092     * @hide
2093     */
2094    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2095            LAYOUT_DIRECTION_LTR,
2096            LAYOUT_DIRECTION_RTL,
2097            LAYOUT_DIRECTION_INHERIT,
2098            LAYOUT_DIRECTION_LOCALE
2099    };
2100
2101    /**
2102     * Default horizontal layout direction.
2103     */
2104    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2105
2106    /**
2107     * Default horizontal layout direction.
2108     * @hide
2109     */
2110    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2111
2112    /**
2113     * Text direction is inherited through {@link ViewGroup}
2114     */
2115    public static final int TEXT_DIRECTION_INHERIT = 0;
2116
2117    /**
2118     * Text direction is using "first strong algorithm". The first strong directional character
2119     * determines the paragraph direction. If there is no strong directional character, the
2120     * paragraph direction is the view's resolved layout direction.
2121     */
2122    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2123
2124    /**
2125     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2126     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2127     * If there are neither, the paragraph direction is the view's resolved layout direction.
2128     */
2129    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2130
2131    /**
2132     * Text direction is forced to LTR.
2133     */
2134    public static final int TEXT_DIRECTION_LTR = 3;
2135
2136    /**
2137     * Text direction is forced to RTL.
2138     */
2139    public static final int TEXT_DIRECTION_RTL = 4;
2140
2141    /**
2142     * Text direction is coming from the system Locale.
2143     */
2144    public static final int TEXT_DIRECTION_LOCALE = 5;
2145
2146    /**
2147     * Text direction is using "first strong algorithm". The first strong directional character
2148     * determines the paragraph direction. If there is no strong directional character, the
2149     * paragraph direction is LTR.
2150     */
2151    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2152
2153    /**
2154     * Text direction is using "first strong algorithm". The first strong directional character
2155     * determines the paragraph direction. If there is no strong directional character, the
2156     * paragraph direction is RTL.
2157     */
2158    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2159
2160    /**
2161     * Default text direction is inherited
2162     */
2163    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2164
2165    /**
2166     * Default resolved text direction
2167     * @hide
2168     */
2169    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2170
2171    /**
2172     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2173     * @hide
2174     */
2175    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2176
2177    /**
2178     * Mask for use with private flags indicating bits used for text direction.
2179     * @hide
2180     */
2181    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2182            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2183
2184    /**
2185     * Array of text direction flags for mapping attribute "textDirection" to correct
2186     * flag value.
2187     * @hide
2188     */
2189    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2190            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2191            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2192            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2193            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2194            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2195            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2196            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2197            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2198    };
2199
2200    /**
2201     * Indicates whether the view text direction has been resolved.
2202     * @hide
2203     */
2204    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2205            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2206
2207    /**
2208     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2209     * @hide
2210     */
2211    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2212
2213    /**
2214     * Mask for use with private flags indicating bits used for resolved text direction.
2215     * @hide
2216     */
2217    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2218            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2219
2220    /**
2221     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2222     * @hide
2223     */
2224    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2225            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2226
2227    /** @hide */
2228    @IntDef({
2229        TEXT_ALIGNMENT_INHERIT,
2230        TEXT_ALIGNMENT_GRAVITY,
2231        TEXT_ALIGNMENT_CENTER,
2232        TEXT_ALIGNMENT_TEXT_START,
2233        TEXT_ALIGNMENT_TEXT_END,
2234        TEXT_ALIGNMENT_VIEW_START,
2235        TEXT_ALIGNMENT_VIEW_END
2236    })
2237    @Retention(RetentionPolicy.SOURCE)
2238    public @interface TextAlignment {}
2239
2240    /**
2241     * Default text alignment. The text alignment of this View is inherited from its parent.
2242     * Use with {@link #setTextAlignment(int)}
2243     */
2244    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2245
2246    /**
2247     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2248     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2249     *
2250     * Use with {@link #setTextAlignment(int)}
2251     */
2252    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2253
2254    /**
2255     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2256     *
2257     * Use with {@link #setTextAlignment(int)}
2258     */
2259    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2260
2261    /**
2262     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2263     *
2264     * Use with {@link #setTextAlignment(int)}
2265     */
2266    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2267
2268    /**
2269     * Center the paragraph, e.g. ALIGN_CENTER.
2270     *
2271     * Use with {@link #setTextAlignment(int)}
2272     */
2273    public static final int TEXT_ALIGNMENT_CENTER = 4;
2274
2275    /**
2276     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2277     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2278     *
2279     * Use with {@link #setTextAlignment(int)}
2280     */
2281    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2282
2283    /**
2284     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2285     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2286     *
2287     * Use with {@link #setTextAlignment(int)}
2288     */
2289    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2290
2291    /**
2292     * Default text alignment is inherited
2293     */
2294    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2295
2296    /**
2297     * Default resolved text alignment
2298     * @hide
2299     */
2300    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2301
2302    /**
2303      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2304      * @hide
2305      */
2306    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2307
2308    /**
2309      * Mask for use with private flags indicating bits used for text alignment.
2310      * @hide
2311      */
2312    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2313
2314    /**
2315     * Array of text direction flags for mapping attribute "textAlignment" to correct
2316     * flag value.
2317     * @hide
2318     */
2319    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2320            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2321            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2322            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2323            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2324            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2325            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2326            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2327    };
2328
2329    /**
2330     * Indicates whether the view text alignment has been resolved.
2331     * @hide
2332     */
2333    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2334
2335    /**
2336     * Bit shift to get the resolved text alignment.
2337     * @hide
2338     */
2339    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2340
2341    /**
2342     * Mask for use with private flags indicating bits used for text alignment.
2343     * @hide
2344     */
2345    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2346            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2347
2348    /**
2349     * Indicates whether if the view text alignment has been resolved to gravity
2350     */
2351    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2352            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2353
2354    // Accessiblity constants for mPrivateFlags2
2355
2356    /**
2357     * Shift for the bits in {@link #mPrivateFlags2} related to the
2358     * "importantForAccessibility" attribute.
2359     */
2360    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2361
2362    /**
2363     * Automatically determine whether a view is important for accessibility.
2364     */
2365    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2366
2367    /**
2368     * The view is important for accessibility.
2369     */
2370    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2371
2372    /**
2373     * The view is not important for accessibility.
2374     */
2375    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2376
2377    /**
2378     * The view is not important for accessibility, nor are any of its
2379     * descendant views.
2380     */
2381    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2382
2383    /**
2384     * The default whether the view is important for accessibility.
2385     */
2386    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2387
2388    /**
2389     * Mask for obtaining the bits which specify how to determine
2390     * whether a view is important for accessibility.
2391     */
2392    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2393        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2394        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2395        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2396
2397    /**
2398     * Shift for the bits in {@link #mPrivateFlags2} related to the
2399     * "accessibilityLiveRegion" attribute.
2400     */
2401    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2402
2403    /**
2404     * Live region mode specifying that accessibility services should not
2405     * automatically announce changes to this view. This is the default live
2406     * region mode for most views.
2407     * <p>
2408     * Use with {@link #setAccessibilityLiveRegion(int)}.
2409     */
2410    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2411
2412    /**
2413     * Live region mode specifying that accessibility services should announce
2414     * changes to this view.
2415     * <p>
2416     * Use with {@link #setAccessibilityLiveRegion(int)}.
2417     */
2418    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2419
2420    /**
2421     * Live region mode specifying that accessibility services should interrupt
2422     * ongoing speech to immediately announce changes to this view.
2423     * <p>
2424     * Use with {@link #setAccessibilityLiveRegion(int)}.
2425     */
2426    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2427
2428    /**
2429     * The default whether the view is important for accessibility.
2430     */
2431    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2432
2433    /**
2434     * Mask for obtaining the bits which specify a view's accessibility live
2435     * region mode.
2436     */
2437    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2438            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2439            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2440
2441    /**
2442     * Flag indicating whether a view has accessibility focus.
2443     */
2444    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2445
2446    /**
2447     * Flag whether the accessibility state of the subtree rooted at this view changed.
2448     */
2449    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2450
2451    /**
2452     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2453     * is used to check whether later changes to the view's transform should invalidate the
2454     * view to force the quickReject test to run again.
2455     */
2456    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2457
2458    /**
2459     * Flag indicating that start/end padding has been resolved into left/right padding
2460     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2461     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2462     * during measurement. In some special cases this is required such as when an adapter-based
2463     * view measures prospective children without attaching them to a window.
2464     */
2465    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2466
2467    /**
2468     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2469     */
2470    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2471
2472    /**
2473     * Indicates that the view is tracking some sort of transient state
2474     * that the app should not need to be aware of, but that the framework
2475     * should take special care to preserve.
2476     */
2477    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2478
2479    /**
2480     * Group of bits indicating that RTL properties resolution is done.
2481     */
2482    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2483            PFLAG2_TEXT_DIRECTION_RESOLVED |
2484            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2485            PFLAG2_PADDING_RESOLVED |
2486            PFLAG2_DRAWABLE_RESOLVED;
2487
2488    // There are a couple of flags left in mPrivateFlags2
2489
2490    /* End of masks for mPrivateFlags2 */
2491
2492    /**
2493     * Masks for mPrivateFlags3, as generated by dumpFlags():
2494     *
2495     * |-------|-------|-------|-------|
2496     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2497     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2498     *                               1   PFLAG3_IS_LAID_OUT
2499     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2500     *                             1     PFLAG3_CALLED_SUPER
2501     *                            1      PFLAG3_APPLYING_INSETS
2502     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2503     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2504     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2505     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2506     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2507     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2508     *                     1             PFLAG3_SCROLL_INDICATOR_START
2509     *                    1              PFLAG3_SCROLL_INDICATOR_END
2510     *                   1               PFLAG3_ASSIST_BLOCKED
2511     *                  1                PFLAG3_CLUSTER
2512     *                 x                 * NO LONGER NEEDED, SHOULD BE REUSED *
2513     *                1                  PFLAG3_FINGER_DOWN
2514     *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2515     *           xxxx                    * NO LONGER NEEDED, SHOULD BE REUSED *
2516     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2517     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2518     *        1                          PFLAG3_TEMPORARY_DETACH
2519     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2520     * |-------|-------|-------|-------|
2521     */
2522
2523    /**
2524     * Flag indicating that view has a transform animation set on it. This is used to track whether
2525     * an animation is cleared between successive frames, in order to tell the associated
2526     * DisplayList to clear its animation matrix.
2527     */
2528    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2529
2530    /**
2531     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2532     * animation is cleared between successive frames, in order to tell the associated
2533     * DisplayList to restore its alpha value.
2534     */
2535    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2536
2537    /**
2538     * Flag indicating that the view has been through at least one layout since it
2539     * was last attached to a window.
2540     */
2541    static final int PFLAG3_IS_LAID_OUT = 0x4;
2542
2543    /**
2544     * Flag indicating that a call to measure() was skipped and should be done
2545     * instead when layout() is invoked.
2546     */
2547    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2548
2549    /**
2550     * Flag indicating that an overridden method correctly called down to
2551     * the superclass implementation as required by the API spec.
2552     */
2553    static final int PFLAG3_CALLED_SUPER = 0x10;
2554
2555    /**
2556     * Flag indicating that we're in the process of applying window insets.
2557     */
2558    static final int PFLAG3_APPLYING_INSETS = 0x20;
2559
2560    /**
2561     * Flag indicating that we're in the process of fitting system windows using the old method.
2562     */
2563    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2564
2565    /**
2566     * Flag indicating that nested scrolling is enabled for this view.
2567     * The view will optionally cooperate with views up its parent chain to allow for
2568     * integrated nested scrolling along the same axis.
2569     */
2570    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2571
2572    /**
2573     * Flag indicating that the bottom scroll indicator should be displayed
2574     * when this view can scroll up.
2575     */
2576    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2577
2578    /**
2579     * Flag indicating that the bottom scroll indicator should be displayed
2580     * when this view can scroll down.
2581     */
2582    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2583
2584    /**
2585     * Flag indicating that the left scroll indicator should be displayed
2586     * when this view can scroll left.
2587     */
2588    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2589
2590    /**
2591     * Flag indicating that the right scroll indicator should be displayed
2592     * when this view can scroll right.
2593     */
2594    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2595
2596    /**
2597     * Flag indicating that the start scroll indicator should be displayed
2598     * when this view can scroll in the start direction.
2599     */
2600    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2601
2602    /**
2603     * Flag indicating that the end scroll indicator should be displayed
2604     * when this view can scroll in the end direction.
2605     */
2606    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2607
2608    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2609
2610    static final int SCROLL_INDICATORS_NONE = 0x0000;
2611
2612    /**
2613     * Mask for use with setFlags indicating bits used for indicating which
2614     * scroll indicators are enabled.
2615     */
2616    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2617            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2618            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2619            | PFLAG3_SCROLL_INDICATOR_END;
2620
2621    /**
2622     * Left-shift required to translate between public scroll indicator flags
2623     * and internal PFLAGS3 flags. When used as a right-shift, translates
2624     * PFLAGS3 flags to public flags.
2625     */
2626    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2627
2628    /** @hide */
2629    @Retention(RetentionPolicy.SOURCE)
2630    @IntDef(flag = true,
2631            value = {
2632                    SCROLL_INDICATOR_TOP,
2633                    SCROLL_INDICATOR_BOTTOM,
2634                    SCROLL_INDICATOR_LEFT,
2635                    SCROLL_INDICATOR_RIGHT,
2636                    SCROLL_INDICATOR_START,
2637                    SCROLL_INDICATOR_END,
2638            })
2639    public @interface ScrollIndicators {}
2640
2641    /**
2642     * Scroll indicator direction for the top edge of the view.
2643     *
2644     * @see #setScrollIndicators(int)
2645     * @see #setScrollIndicators(int, int)
2646     * @see #getScrollIndicators()
2647     */
2648    public static final int SCROLL_INDICATOR_TOP =
2649            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2650
2651    /**
2652     * Scroll indicator direction for the bottom edge of the view.
2653     *
2654     * @see #setScrollIndicators(int)
2655     * @see #setScrollIndicators(int, int)
2656     * @see #getScrollIndicators()
2657     */
2658    public static final int SCROLL_INDICATOR_BOTTOM =
2659            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2660
2661    /**
2662     * Scroll indicator direction for the left edge of the view.
2663     *
2664     * @see #setScrollIndicators(int)
2665     * @see #setScrollIndicators(int, int)
2666     * @see #getScrollIndicators()
2667     */
2668    public static final int SCROLL_INDICATOR_LEFT =
2669            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2670
2671    /**
2672     * Scroll indicator direction for the right edge of the view.
2673     *
2674     * @see #setScrollIndicators(int)
2675     * @see #setScrollIndicators(int, int)
2676     * @see #getScrollIndicators()
2677     */
2678    public static final int SCROLL_INDICATOR_RIGHT =
2679            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2680
2681    /**
2682     * Scroll indicator direction for the starting edge of the view.
2683     * <p>
2684     * Resolved according to the view's layout direction, see
2685     * {@link #getLayoutDirection()} for more information.
2686     *
2687     * @see #setScrollIndicators(int)
2688     * @see #setScrollIndicators(int, int)
2689     * @see #getScrollIndicators()
2690     */
2691    public static final int SCROLL_INDICATOR_START =
2692            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2693
2694    /**
2695     * Scroll indicator direction for the ending edge of the view.
2696     * <p>
2697     * Resolved according to the view's layout direction, see
2698     * {@link #getLayoutDirection()} for more information.
2699     *
2700     * @see #setScrollIndicators(int)
2701     * @see #setScrollIndicators(int, int)
2702     * @see #getScrollIndicators()
2703     */
2704    public static final int SCROLL_INDICATOR_END =
2705            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2706
2707    /**
2708     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2709     * into this view.<p>
2710     */
2711    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2712
2713    /**
2714     * Flag indicating that the view is a root of a keyboard navigation cluster.
2715     *
2716     * @see #isKeyboardNavigationCluster()
2717     * @see #setKeyboardNavigationCluster(boolean)
2718     */
2719    private static final int PFLAG3_CLUSTER = 0x8000;
2720
2721    /**
2722     * Indicates that the user is currently touching the screen.
2723     * Currently used for the tooltip positioning only.
2724     */
2725    private static final int PFLAG3_FINGER_DOWN = 0x20000;
2726
2727    /**
2728     * Flag indicating that this view is the default-focus view.
2729     *
2730     * @see #isFocusedByDefault()
2731     * @see #setFocusedByDefault(boolean)
2732     */
2733    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
2734
2735    /**
2736     * Whether this view has rendered elements that overlap (see {@link
2737     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2738     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2739     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2740     * determined by whatever {@link #hasOverlappingRendering()} returns.
2741     */
2742    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2743
2744    /**
2745     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2746     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2747     */
2748    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2749
2750    /**
2751     * Flag indicating that the view is temporarily detached from the parent view.
2752     *
2753     * @see #onStartTemporaryDetach()
2754     * @see #onFinishTemporaryDetach()
2755     */
2756    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
2757
2758    /**
2759     * Flag indicating that the view does not wish to be revealed within its parent
2760     * hierarchy when it gains focus. Expressed in the negative since the historical
2761     * default behavior is to reveal on focus; this flag suppresses that behavior.
2762     *
2763     * @see #setRevealOnFocusHint(boolean)
2764     * @see #getRevealOnFocusHint()
2765     */
2766    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
2767
2768    /* End of masks for mPrivateFlags3 */
2769
2770    /**
2771     * Always allow a user to over-scroll this view, provided it is a
2772     * view that can scroll.
2773     *
2774     * @see #getOverScrollMode()
2775     * @see #setOverScrollMode(int)
2776     */
2777    public static final int OVER_SCROLL_ALWAYS = 0;
2778
2779    /**
2780     * Allow a user to over-scroll this view only if the content is large
2781     * enough to meaningfully scroll, provided it is a view that can scroll.
2782     *
2783     * @see #getOverScrollMode()
2784     * @see #setOverScrollMode(int)
2785     */
2786    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2787
2788    /**
2789     * Never allow a user to over-scroll this view.
2790     *
2791     * @see #getOverScrollMode()
2792     * @see #setOverScrollMode(int)
2793     */
2794    public static final int OVER_SCROLL_NEVER = 2;
2795
2796    /**
2797     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2798     * requested the system UI (status bar) to be visible (the default).
2799     *
2800     * @see #setSystemUiVisibility(int)
2801     */
2802    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2803
2804    /**
2805     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2806     * system UI to enter an unobtrusive "low profile" mode.
2807     *
2808     * <p>This is for use in games, book readers, video players, or any other
2809     * "immersive" application where the usual system chrome is deemed too distracting.
2810     *
2811     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2812     *
2813     * @see #setSystemUiVisibility(int)
2814     */
2815    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2816
2817    /**
2818     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2819     * system navigation be temporarily hidden.
2820     *
2821     * <p>This is an even less obtrusive state than that called for by
2822     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2823     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2824     * those to disappear. This is useful (in conjunction with the
2825     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2826     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2827     * window flags) for displaying content using every last pixel on the display.
2828     *
2829     * <p>There is a limitation: because navigation controls are so important, the least user
2830     * interaction will cause them to reappear immediately.  When this happens, both
2831     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2832     * so that both elements reappear at the same time.
2833     *
2834     * @see #setSystemUiVisibility(int)
2835     */
2836    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2837
2838    /**
2839     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2840     * into the normal fullscreen mode so that its content can take over the screen
2841     * while still allowing the user to interact with the application.
2842     *
2843     * <p>This has the same visual effect as
2844     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2845     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2846     * meaning that non-critical screen decorations (such as the status bar) will be
2847     * hidden while the user is in the View's window, focusing the experience on
2848     * that content.  Unlike the window flag, if you are using ActionBar in
2849     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2850     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2851     * hide the action bar.
2852     *
2853     * <p>This approach to going fullscreen is best used over the window flag when
2854     * it is a transient state -- that is, the application does this at certain
2855     * points in its user interaction where it wants to allow the user to focus
2856     * on content, but not as a continuous state.  For situations where the application
2857     * would like to simply stay full screen the entire time (such as a game that
2858     * wants to take over the screen), the
2859     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2860     * is usually a better approach.  The state set here will be removed by the system
2861     * in various situations (such as the user moving to another application) like
2862     * the other system UI states.
2863     *
2864     * <p>When using this flag, the application should provide some easy facility
2865     * for the user to go out of it.  A common example would be in an e-book
2866     * reader, where tapping on the screen brings back whatever screen and UI
2867     * decorations that had been hidden while the user was immersed in reading
2868     * the book.
2869     *
2870     * @see #setSystemUiVisibility(int)
2871     */
2872    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2873
2874    /**
2875     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2876     * flags, we would like a stable view of the content insets given to
2877     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2878     * will always represent the worst case that the application can expect
2879     * as a continuous state.  In the stock Android UI this is the space for
2880     * the system bar, nav bar, and status bar, but not more transient elements
2881     * such as an input method.
2882     *
2883     * The stable layout your UI sees is based on the system UI modes you can
2884     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2885     * then you will get a stable layout for changes of the
2886     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2887     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2888     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2889     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2890     * with a stable layout.  (Note that you should avoid using
2891     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2892     *
2893     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2894     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2895     * then a hidden status bar will be considered a "stable" state for purposes
2896     * here.  This allows your UI to continually hide the status bar, while still
2897     * using the system UI flags to hide the action bar while still retaining
2898     * a stable layout.  Note that changing the window fullscreen flag will never
2899     * provide a stable layout for a clean transition.
2900     *
2901     * <p>If you are using ActionBar in
2902     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2903     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2904     * insets it adds to those given to the application.
2905     */
2906    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2907
2908    /**
2909     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2910     * to be laid out as if it has requested
2911     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2912     * allows it to avoid artifacts when switching in and out of that mode, at
2913     * the expense that some of its user interface may be covered by screen
2914     * decorations when they are shown.  You can perform layout of your inner
2915     * UI elements to account for the navigation system UI through the
2916     * {@link #fitSystemWindows(Rect)} method.
2917     */
2918    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2919
2920    /**
2921     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2922     * to be laid out as if it has requested
2923     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2924     * allows it to avoid artifacts when switching in and out of that mode, at
2925     * the expense that some of its user interface may be covered by screen
2926     * decorations when they are shown.  You can perform layout of your inner
2927     * UI elements to account for non-fullscreen system UI through the
2928     * {@link #fitSystemWindows(Rect)} method.
2929     */
2930    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2931
2932    /**
2933     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2934     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2935     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2936     * user interaction.
2937     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2938     * has an effect when used in combination with that flag.</p>
2939     */
2940    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2941
2942    /**
2943     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2944     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2945     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2946     * experience while also hiding the system bars.  If this flag is not set,
2947     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2948     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2949     * if the user swipes from the top of the screen.
2950     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2951     * system gestures, such as swiping from the top of the screen.  These transient system bars
2952     * will overlay app’s content, may have some degree of transparency, and will automatically
2953     * hide after a short timeout.
2954     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2955     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2956     * with one or both of those flags.</p>
2957     */
2958    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2959
2960    /**
2961     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2962     * is compatible with light status bar backgrounds.
2963     *
2964     * <p>For this to take effect, the window must request
2965     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2966     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2967     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2968     *         FLAG_TRANSLUCENT_STATUS}.
2969     *
2970     * @see android.R.attr#windowLightStatusBar
2971     */
2972    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2973
2974    /**
2975     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
2976     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
2977     */
2978    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
2979
2980    /**
2981     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
2982     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
2983     */
2984    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
2985
2986    /**
2987     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
2988     * that is compatible with light navigation bar backgrounds.
2989     *
2990     * <p>For this to take effect, the window must request
2991     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2992     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2993     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
2994     *         FLAG_TRANSLUCENT_NAVIGATION}.
2995     */
2996    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
2997
2998    /**
2999     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3000     */
3001    @Deprecated
3002    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3003
3004    /**
3005     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3006     */
3007    @Deprecated
3008    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3009
3010    /**
3011     * @hide
3012     *
3013     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3014     * out of the public fields to keep the undefined bits out of the developer's way.
3015     *
3016     * Flag to make the status bar not expandable.  Unless you also
3017     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3018     */
3019    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3020
3021    /**
3022     * @hide
3023     *
3024     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3025     * out of the public fields to keep the undefined bits out of the developer's way.
3026     *
3027     * Flag to hide notification icons and scrolling ticker text.
3028     */
3029    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3030
3031    /**
3032     * @hide
3033     *
3034     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3035     * out of the public fields to keep the undefined bits out of the developer's way.
3036     *
3037     * Flag to disable incoming notification alerts.  This will not block
3038     * icons, but it will block sound, vibrating and other visual or aural notifications.
3039     */
3040    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3041
3042    /**
3043     * @hide
3044     *
3045     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3046     * out of the public fields to keep the undefined bits out of the developer's way.
3047     *
3048     * Flag to hide only the scrolling ticker.  Note that
3049     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3050     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3051     */
3052    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3053
3054    /**
3055     * @hide
3056     *
3057     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3058     * out of the public fields to keep the undefined bits out of the developer's way.
3059     *
3060     * Flag to hide the center system info area.
3061     */
3062    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3063
3064    /**
3065     * @hide
3066     *
3067     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3068     * out of the public fields to keep the undefined bits out of the developer's way.
3069     *
3070     * Flag to hide only the home button.  Don't use this
3071     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3072     */
3073    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3074
3075    /**
3076     * @hide
3077     *
3078     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3079     * out of the public fields to keep the undefined bits out of the developer's way.
3080     *
3081     * Flag to hide only the back button. Don't use this
3082     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3083     */
3084    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3085
3086    /**
3087     * @hide
3088     *
3089     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3090     * out of the public fields to keep the undefined bits out of the developer's way.
3091     *
3092     * Flag to hide only the clock.  You might use this if your activity has
3093     * its own clock making the status bar's clock redundant.
3094     */
3095    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3096
3097    /**
3098     * @hide
3099     *
3100     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3101     * out of the public fields to keep the undefined bits out of the developer's way.
3102     *
3103     * Flag to hide only the recent apps button. Don't use this
3104     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3105     */
3106    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3107
3108    /**
3109     * @hide
3110     *
3111     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3112     * out of the public fields to keep the undefined bits out of the developer's way.
3113     *
3114     * Flag to disable the global search gesture. Don't use this
3115     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3116     */
3117    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3118
3119    /**
3120     * @hide
3121     *
3122     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3123     * out of the public fields to keep the undefined bits out of the developer's way.
3124     *
3125     * Flag to specify that the status bar is displayed in transient mode.
3126     */
3127    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3128
3129    /**
3130     * @hide
3131     *
3132     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3133     * out of the public fields to keep the undefined bits out of the developer's way.
3134     *
3135     * Flag to specify that the navigation bar is displayed in transient mode.
3136     */
3137    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3138
3139    /**
3140     * @hide
3141     *
3142     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3143     * out of the public fields to keep the undefined bits out of the developer's way.
3144     *
3145     * Flag to specify that the hidden status bar would like to be shown.
3146     */
3147    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3148
3149    /**
3150     * @hide
3151     *
3152     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3153     * out of the public fields to keep the undefined bits out of the developer's way.
3154     *
3155     * Flag to specify that the hidden navigation bar would like to be shown.
3156     */
3157    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3158
3159    /**
3160     * @hide
3161     *
3162     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3163     * out of the public fields to keep the undefined bits out of the developer's way.
3164     *
3165     * Flag to specify that the status bar is displayed in translucent mode.
3166     */
3167    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3168
3169    /**
3170     * @hide
3171     *
3172     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3173     * out of the public fields to keep the undefined bits out of the developer's way.
3174     *
3175     * Flag to specify that the navigation bar is displayed in translucent mode.
3176     */
3177    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3178
3179    /**
3180     * @hide
3181     *
3182     * Makes navigation bar transparent (but not the status bar).
3183     */
3184    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3185
3186    /**
3187     * @hide
3188     *
3189     * Makes status bar transparent (but not the navigation bar).
3190     */
3191    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3192
3193    /**
3194     * @hide
3195     *
3196     * Makes both status bar and navigation bar transparent.
3197     */
3198    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3199            | STATUS_BAR_TRANSPARENT;
3200
3201    /**
3202     * @hide
3203     */
3204    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3205
3206    /**
3207     * These are the system UI flags that can be cleared by events outside
3208     * of an application.  Currently this is just the ability to tap on the
3209     * screen while hiding the navigation bar to have it return.
3210     * @hide
3211     */
3212    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3213            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3214            | SYSTEM_UI_FLAG_FULLSCREEN;
3215
3216    /**
3217     * Flags that can impact the layout in relation to system UI.
3218     */
3219    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3220            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3221            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3222
3223    /** @hide */
3224    @IntDef(flag = true,
3225            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3226    @Retention(RetentionPolicy.SOURCE)
3227    public @interface FindViewFlags {}
3228
3229    /**
3230     * Find views that render the specified text.
3231     *
3232     * @see #findViewsWithText(ArrayList, CharSequence, int)
3233     */
3234    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3235
3236    /**
3237     * Find find views that contain the specified content description.
3238     *
3239     * @see #findViewsWithText(ArrayList, CharSequence, int)
3240     */
3241    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3242
3243    /**
3244     * Find views that contain {@link AccessibilityNodeProvider}. Such
3245     * a View is a root of virtual view hierarchy and may contain the searched
3246     * text. If this flag is set Views with providers are automatically
3247     * added and it is a responsibility of the client to call the APIs of
3248     * the provider to determine whether the virtual tree rooted at this View
3249     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3250     * representing the virtual views with this text.
3251     *
3252     * @see #findViewsWithText(ArrayList, CharSequence, int)
3253     *
3254     * @hide
3255     */
3256    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3257
3258    /**
3259     * The undefined cursor position.
3260     *
3261     * @hide
3262     */
3263    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3264
3265    /**
3266     * Indicates that the screen has changed state and is now off.
3267     *
3268     * @see #onScreenStateChanged(int)
3269     */
3270    public static final int SCREEN_STATE_OFF = 0x0;
3271
3272    /**
3273     * Indicates that the screen has changed state and is now on.
3274     *
3275     * @see #onScreenStateChanged(int)
3276     */
3277    public static final int SCREEN_STATE_ON = 0x1;
3278
3279    /**
3280     * Indicates no axis of view scrolling.
3281     */
3282    public static final int SCROLL_AXIS_NONE = 0;
3283
3284    /**
3285     * Indicates scrolling along the horizontal axis.
3286     */
3287    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3288
3289    /**
3290     * Indicates scrolling along the vertical axis.
3291     */
3292    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3293
3294    /**
3295     * Controls the over-scroll mode for this view.
3296     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3297     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3298     * and {@link #OVER_SCROLL_NEVER}.
3299     */
3300    private int mOverScrollMode;
3301
3302    /**
3303     * The parent this view is attached to.
3304     * {@hide}
3305     *
3306     * @see #getParent()
3307     */
3308    protected ViewParent mParent;
3309
3310    /**
3311     * {@hide}
3312     */
3313    AttachInfo mAttachInfo;
3314
3315    /**
3316     * {@hide}
3317     */
3318    @ViewDebug.ExportedProperty(flagMapping = {
3319        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3320                name = "FORCE_LAYOUT"),
3321        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3322                name = "LAYOUT_REQUIRED"),
3323        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3324            name = "DRAWING_CACHE_INVALID", outputIf = false),
3325        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3326        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3327        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3328        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3329    }, formatToHexString = true)
3330
3331    /* @hide */
3332    public int mPrivateFlags;
3333    int mPrivateFlags2;
3334    int mPrivateFlags3;
3335
3336    /**
3337     * This view's request for the visibility of the status bar.
3338     * @hide
3339     */
3340    @ViewDebug.ExportedProperty(flagMapping = {
3341        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3342                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3343                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3344        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3345                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3346                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3347        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3348                                equals = SYSTEM_UI_FLAG_VISIBLE,
3349                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3350    }, formatToHexString = true)
3351    int mSystemUiVisibility;
3352
3353    /**
3354     * Reference count for transient state.
3355     * @see #setHasTransientState(boolean)
3356     */
3357    int mTransientStateCount = 0;
3358
3359    /**
3360     * Count of how many windows this view has been attached to.
3361     */
3362    int mWindowAttachCount;
3363
3364    /**
3365     * The layout parameters associated with this view and used by the parent
3366     * {@link android.view.ViewGroup} to determine how this view should be
3367     * laid out.
3368     * {@hide}
3369     */
3370    protected ViewGroup.LayoutParams mLayoutParams;
3371
3372    /**
3373     * The view flags hold various views states.
3374     * {@hide}
3375     */
3376    @ViewDebug.ExportedProperty(formatToHexString = true)
3377    int mViewFlags;
3378
3379    static class TransformationInfo {
3380        /**
3381         * The transform matrix for the View. This transform is calculated internally
3382         * based on the translation, rotation, and scale properties.
3383         *
3384         * Do *not* use this variable directly; instead call getMatrix(), which will
3385         * load the value from the View's RenderNode.
3386         */
3387        private final Matrix mMatrix = new Matrix();
3388
3389        /**
3390         * The inverse transform matrix for the View. This transform is calculated
3391         * internally based on the translation, rotation, and scale properties.
3392         *
3393         * Do *not* use this variable directly; instead call getInverseMatrix(),
3394         * which will load the value from the View's RenderNode.
3395         */
3396        private Matrix mInverseMatrix;
3397
3398        /**
3399         * The opacity of the View. This is a value from 0 to 1, where 0 means
3400         * completely transparent and 1 means completely opaque.
3401         */
3402        @ViewDebug.ExportedProperty
3403        float mAlpha = 1f;
3404
3405        /**
3406         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3407         * property only used by transitions, which is composited with the other alpha
3408         * values to calculate the final visual alpha value.
3409         */
3410        float mTransitionAlpha = 1f;
3411    }
3412
3413    /** @hide */
3414    public TransformationInfo mTransformationInfo;
3415
3416    /**
3417     * Current clip bounds. to which all drawing of this view are constrained.
3418     */
3419    Rect mClipBounds = null;
3420
3421    private boolean mLastIsOpaque;
3422
3423    /**
3424     * The distance in pixels from the left edge of this view's parent
3425     * to the left edge of this view.
3426     * {@hide}
3427     */
3428    @ViewDebug.ExportedProperty(category = "layout")
3429    protected int mLeft;
3430    /**
3431     * The distance in pixels from the left edge of this view's parent
3432     * to the right edge of this view.
3433     * {@hide}
3434     */
3435    @ViewDebug.ExportedProperty(category = "layout")
3436    protected int mRight;
3437    /**
3438     * The distance in pixels from the top edge of this view's parent
3439     * to the top edge of this view.
3440     * {@hide}
3441     */
3442    @ViewDebug.ExportedProperty(category = "layout")
3443    protected int mTop;
3444    /**
3445     * The distance in pixels from the top edge of this view's parent
3446     * to the bottom edge of this view.
3447     * {@hide}
3448     */
3449    @ViewDebug.ExportedProperty(category = "layout")
3450    protected int mBottom;
3451
3452    /**
3453     * The offset, in pixels, by which the content of this view is scrolled
3454     * horizontally.
3455     * {@hide}
3456     */
3457    @ViewDebug.ExportedProperty(category = "scrolling")
3458    protected int mScrollX;
3459    /**
3460     * The offset, in pixels, by which the content of this view is scrolled
3461     * vertically.
3462     * {@hide}
3463     */
3464    @ViewDebug.ExportedProperty(category = "scrolling")
3465    protected int mScrollY;
3466
3467    /**
3468     * The left padding in pixels, that is the distance in pixels between the
3469     * left edge of this view and the left edge of its content.
3470     * {@hide}
3471     */
3472    @ViewDebug.ExportedProperty(category = "padding")
3473    protected int mPaddingLeft = 0;
3474    /**
3475     * The right padding in pixels, that is the distance in pixels between the
3476     * right edge of this view and the right edge of its content.
3477     * {@hide}
3478     */
3479    @ViewDebug.ExportedProperty(category = "padding")
3480    protected int mPaddingRight = 0;
3481    /**
3482     * The top padding in pixels, that is the distance in pixels between the
3483     * top edge of this view and the top edge of its content.
3484     * {@hide}
3485     */
3486    @ViewDebug.ExportedProperty(category = "padding")
3487    protected int mPaddingTop;
3488    /**
3489     * The bottom padding in pixels, that is the distance in pixels between the
3490     * bottom edge of this view and the bottom edge of its content.
3491     * {@hide}
3492     */
3493    @ViewDebug.ExportedProperty(category = "padding")
3494    protected int mPaddingBottom;
3495
3496    /**
3497     * The layout insets in pixels, that is the distance in pixels between the
3498     * visible edges of this view its bounds.
3499     */
3500    private Insets mLayoutInsets;
3501
3502    /**
3503     * Briefly describes the view and is primarily used for accessibility support.
3504     */
3505    private CharSequence mContentDescription;
3506
3507    /**
3508     * Specifies the id of a view for which this view serves as a label for
3509     * accessibility purposes.
3510     */
3511    private int mLabelForId = View.NO_ID;
3512
3513    /**
3514     * Predicate for matching labeled view id with its label for
3515     * accessibility purposes.
3516     */
3517    private MatchLabelForPredicate mMatchLabelForPredicate;
3518
3519    /**
3520     * Specifies a view before which this one is visited in accessibility traversal.
3521     */
3522    private int mAccessibilityTraversalBeforeId = NO_ID;
3523
3524    /**
3525     * Specifies a view after which this one is visited in accessibility traversal.
3526     */
3527    private int mAccessibilityTraversalAfterId = NO_ID;
3528
3529    /**
3530     * Predicate for matching a view by its id.
3531     */
3532    private MatchIdPredicate mMatchIdPredicate;
3533
3534    /**
3535     * Cache the paddingRight set by the user to append to the scrollbar's size.
3536     *
3537     * @hide
3538     */
3539    @ViewDebug.ExportedProperty(category = "padding")
3540    protected int mUserPaddingRight;
3541
3542    /**
3543     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3544     *
3545     * @hide
3546     */
3547    @ViewDebug.ExportedProperty(category = "padding")
3548    protected int mUserPaddingBottom;
3549
3550    /**
3551     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3552     *
3553     * @hide
3554     */
3555    @ViewDebug.ExportedProperty(category = "padding")
3556    protected int mUserPaddingLeft;
3557
3558    /**
3559     * Cache the paddingStart set by the user to append to the scrollbar's size.
3560     *
3561     */
3562    @ViewDebug.ExportedProperty(category = "padding")
3563    int mUserPaddingStart;
3564
3565    /**
3566     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3567     *
3568     */
3569    @ViewDebug.ExportedProperty(category = "padding")
3570    int mUserPaddingEnd;
3571
3572    /**
3573     * Cache initial left padding.
3574     *
3575     * @hide
3576     */
3577    int mUserPaddingLeftInitial;
3578
3579    /**
3580     * Cache initial right padding.
3581     *
3582     * @hide
3583     */
3584    int mUserPaddingRightInitial;
3585
3586    /**
3587     * Default undefined padding
3588     */
3589    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3590
3591    /**
3592     * Cache if a left padding has been defined
3593     */
3594    private boolean mLeftPaddingDefined = false;
3595
3596    /**
3597     * Cache if a right padding has been defined
3598     */
3599    private boolean mRightPaddingDefined = false;
3600
3601    /**
3602     * @hide
3603     */
3604    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3605    /**
3606     * @hide
3607     */
3608    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3609
3610    private LongSparseLongArray mMeasureCache;
3611
3612    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3613    private Drawable mBackground;
3614    private TintInfo mBackgroundTint;
3615
3616    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3617    private ForegroundInfo mForegroundInfo;
3618
3619    private Drawable mScrollIndicatorDrawable;
3620
3621    /**
3622     * RenderNode used for backgrounds.
3623     * <p>
3624     * When non-null and valid, this is expected to contain an up-to-date copy
3625     * of the background drawable. It is cleared on temporary detach, and reset
3626     * on cleanup.
3627     */
3628    private RenderNode mBackgroundRenderNode;
3629
3630    private int mBackgroundResource;
3631    private boolean mBackgroundSizeChanged;
3632
3633    private String mTransitionName;
3634
3635    static class TintInfo {
3636        ColorStateList mTintList;
3637        PorterDuff.Mode mTintMode;
3638        boolean mHasTintMode;
3639        boolean mHasTintList;
3640    }
3641
3642    private static class ForegroundInfo {
3643        private Drawable mDrawable;
3644        private TintInfo mTintInfo;
3645        private int mGravity = Gravity.FILL;
3646        private boolean mInsidePadding = true;
3647        private boolean mBoundsChanged = true;
3648        private final Rect mSelfBounds = new Rect();
3649        private final Rect mOverlayBounds = new Rect();
3650    }
3651
3652    static class ListenerInfo {
3653        /**
3654         * Listener used to dispatch focus change events.
3655         * This field should be made private, so it is hidden from the SDK.
3656         * {@hide}
3657         */
3658        protected OnFocusChangeListener mOnFocusChangeListener;
3659
3660        /**
3661         * Listeners for layout change events.
3662         */
3663        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3664
3665        protected OnScrollChangeListener mOnScrollChangeListener;
3666
3667        /**
3668         * Listeners for attach events.
3669         */
3670        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3671
3672        /**
3673         * Listener used to dispatch click events.
3674         * This field should be made private, so it is hidden from the SDK.
3675         * {@hide}
3676         */
3677        public OnClickListener mOnClickListener;
3678
3679        /**
3680         * Listener used to dispatch long click events.
3681         * This field should be made private, so it is hidden from the SDK.
3682         * {@hide}
3683         */
3684        protected OnLongClickListener mOnLongClickListener;
3685
3686        /**
3687         * Listener used to dispatch context click events. This field should be made private, so it
3688         * is hidden from the SDK.
3689         * {@hide}
3690         */
3691        protected OnContextClickListener mOnContextClickListener;
3692
3693        /**
3694         * Listener used to build the context menu.
3695         * This field should be made private, so it is hidden from the SDK.
3696         * {@hide}
3697         */
3698        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3699
3700        private OnKeyListener mOnKeyListener;
3701
3702        private OnTouchListener mOnTouchListener;
3703
3704        private OnHoverListener mOnHoverListener;
3705
3706        private OnGenericMotionListener mOnGenericMotionListener;
3707
3708        private OnDragListener mOnDragListener;
3709
3710        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3711
3712        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3713
3714        OnCapturedPointerListener mOnCapturedPointerListener;
3715    }
3716
3717    ListenerInfo mListenerInfo;
3718
3719    private static class TooltipInfo {
3720        /**
3721         * Text to be displayed in a tooltip popup.
3722         */
3723        @Nullable
3724        CharSequence mTooltipText;
3725
3726        /**
3727         * View-relative position of the tooltip anchor point.
3728         */
3729        int mAnchorX;
3730        int mAnchorY;
3731
3732        /**
3733         * The tooltip popup.
3734         */
3735        @Nullable
3736        TooltipPopup mTooltipPopup;
3737
3738        /**
3739         * Set to true if the tooltip was shown as a result of a long click.
3740         */
3741        boolean mTooltipFromLongClick;
3742
3743        /**
3744         * Keep these Runnables so that they can be used to reschedule.
3745         */
3746        Runnable mShowTooltipRunnable;
3747        Runnable mHideTooltipRunnable;
3748    }
3749
3750    TooltipInfo mTooltipInfo;
3751
3752    // Temporary values used to hold (x,y) coordinates when delegating from the
3753    // two-arg performLongClick() method to the legacy no-arg version.
3754    private float mLongClickX = Float.NaN;
3755    private float mLongClickY = Float.NaN;
3756
3757    /**
3758     * The application environment this view lives in.
3759     * This field should be made private, so it is hidden from the SDK.
3760     * {@hide}
3761     */
3762    @ViewDebug.ExportedProperty(deepExport = true)
3763    protected Context mContext;
3764
3765    private final Resources mResources;
3766
3767    private ScrollabilityCache mScrollCache;
3768
3769    private int[] mDrawableState = null;
3770
3771    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3772
3773    /**
3774     * Animator that automatically runs based on state changes.
3775     */
3776    private StateListAnimator mStateListAnimator;
3777
3778    /**
3779     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3780     * the user may specify which view to go to next.
3781     */
3782    private int mNextFocusLeftId = View.NO_ID;
3783
3784    /**
3785     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3786     * the user may specify which view to go to next.
3787     */
3788    private int mNextFocusRightId = View.NO_ID;
3789
3790    /**
3791     * When this view has focus and the next focus is {@link #FOCUS_UP},
3792     * the user may specify which view to go to next.
3793     */
3794    private int mNextFocusUpId = View.NO_ID;
3795
3796    /**
3797     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3798     * the user may specify which view to go to next.
3799     */
3800    private int mNextFocusDownId = View.NO_ID;
3801
3802    /**
3803     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3804     * the user may specify which view to go to next.
3805     */
3806    int mNextFocusForwardId = View.NO_ID;
3807
3808    /**
3809     * User-specified next keyboard navigation cluster.
3810     */
3811    int mNextClusterForwardId = View.NO_ID;
3812
3813    private CheckForLongPress mPendingCheckForLongPress;
3814    private CheckForTap mPendingCheckForTap = null;
3815    private PerformClick mPerformClick;
3816    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3817
3818    private UnsetPressedState mUnsetPressedState;
3819
3820    /**
3821     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3822     * up event while a long press is invoked as soon as the long press duration is reached, so
3823     * a long press could be performed before the tap is checked, in which case the tap's action
3824     * should not be invoked.
3825     */
3826    private boolean mHasPerformedLongPress;
3827
3828    /**
3829     * Whether a context click button is currently pressed down. This is true when the stylus is
3830     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3831     * pressed. This is false once the button is released or if the stylus has been lifted.
3832     */
3833    private boolean mInContextButtonPress;
3834
3835    /**
3836     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3837     * true after a stylus button press has occured, when the next up event should not be recognized
3838     * as a tap.
3839     */
3840    private boolean mIgnoreNextUpEvent;
3841
3842    /**
3843     * The minimum height of the view. We'll try our best to have the height
3844     * of this view to at least this amount.
3845     */
3846    @ViewDebug.ExportedProperty(category = "measurement")
3847    private int mMinHeight;
3848
3849    /**
3850     * The minimum width of the view. We'll try our best to have the width
3851     * of this view to at least this amount.
3852     */
3853    @ViewDebug.ExportedProperty(category = "measurement")
3854    private int mMinWidth;
3855
3856    /**
3857     * The delegate to handle touch events that are physically in this view
3858     * but should be handled by another view.
3859     */
3860    private TouchDelegate mTouchDelegate = null;
3861
3862    /**
3863     * Solid color to use as a background when creating the drawing cache. Enables
3864     * the cache to use 16 bit bitmaps instead of 32 bit.
3865     */
3866    private int mDrawingCacheBackgroundColor = 0;
3867
3868    /**
3869     * Special tree observer used when mAttachInfo is null.
3870     */
3871    private ViewTreeObserver mFloatingTreeObserver;
3872
3873    /**
3874     * Cache the touch slop from the context that created the view.
3875     */
3876    private int mTouchSlop;
3877
3878    /**
3879     * Object that handles automatic animation of view properties.
3880     */
3881    private ViewPropertyAnimator mAnimator = null;
3882
3883    /**
3884     * List of registered FrameMetricsObservers.
3885     */
3886    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
3887
3888    /**
3889     * Flag indicating that a drag can cross window boundaries.  When
3890     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3891     * with this flag set, all visible applications with targetSdkVersion >=
3892     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
3893     * in the drag operation and receive the dragged content.
3894     *
3895     * <p>If this is the only flag set, then the drag recipient will only have access to text data
3896     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3897     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
3898     */
3899    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3900
3901    /**
3902     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3903     * request read access to the content URI(s) contained in the {@link ClipData} object.
3904     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3905     */
3906    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3907
3908    /**
3909     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3910     * request write access to the content URI(s) contained in the {@link ClipData} object.
3911     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3912     */
3913    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3914
3915    /**
3916     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3917     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3918     * reboots until explicitly revoked with
3919     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3920     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3921     */
3922    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3923            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3924
3925    /**
3926     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3927     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3928     * match against the original granted URI.
3929     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3930     */
3931    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3932            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3933
3934    /**
3935     * Flag indicating that the drag shadow will be opaque.  When
3936     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
3937     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3938     */
3939    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3940
3941    /**
3942     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3943     */
3944    private float mVerticalScrollFactor;
3945
3946    /**
3947     * Position of the vertical scroll bar.
3948     */
3949    private int mVerticalScrollbarPosition;
3950
3951    /**
3952     * Position the scroll bar at the default position as determined by the system.
3953     */
3954    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3955
3956    /**
3957     * Position the scroll bar along the left edge.
3958     */
3959    public static final int SCROLLBAR_POSITION_LEFT = 1;
3960
3961    /**
3962     * Position the scroll bar along the right edge.
3963     */
3964    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3965
3966    /**
3967     * Indicates that the view does not have a layer.
3968     *
3969     * @see #getLayerType()
3970     * @see #setLayerType(int, android.graphics.Paint)
3971     * @see #LAYER_TYPE_SOFTWARE
3972     * @see #LAYER_TYPE_HARDWARE
3973     */
3974    public static final int LAYER_TYPE_NONE = 0;
3975
3976    /**
3977     * <p>Indicates that the view has a software layer. A software layer is backed
3978     * by a bitmap and causes the view to be rendered using Android's software
3979     * rendering pipeline, even if hardware acceleration is enabled.</p>
3980     *
3981     * <p>Software layers have various usages:</p>
3982     * <p>When the application is not using hardware acceleration, a software layer
3983     * is useful to apply a specific color filter and/or blending mode and/or
3984     * translucency to a view and all its children.</p>
3985     * <p>When the application is using hardware acceleration, a software layer
3986     * is useful to render drawing primitives not supported by the hardware
3987     * accelerated pipeline. It can also be used to cache a complex view tree
3988     * into a texture and reduce the complexity of drawing operations. For instance,
3989     * when animating a complex view tree with a translation, a software layer can
3990     * be used to render the view tree only once.</p>
3991     * <p>Software layers should be avoided when the affected view tree updates
3992     * often. Every update will require to re-render the software layer, which can
3993     * potentially be slow (particularly when hardware acceleration is turned on
3994     * since the layer will have to be uploaded into a hardware texture after every
3995     * update.)</p>
3996     *
3997     * @see #getLayerType()
3998     * @see #setLayerType(int, android.graphics.Paint)
3999     * @see #LAYER_TYPE_NONE
4000     * @see #LAYER_TYPE_HARDWARE
4001     */
4002    public static final int LAYER_TYPE_SOFTWARE = 1;
4003
4004    /**
4005     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4006     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4007     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4008     * rendering pipeline, but only if hardware acceleration is turned on for the
4009     * view hierarchy. When hardware acceleration is turned off, hardware layers
4010     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4011     *
4012     * <p>A hardware layer is useful to apply a specific color filter and/or
4013     * blending mode and/or translucency to a view and all its children.</p>
4014     * <p>A hardware layer can be used to cache a complex view tree into a
4015     * texture and reduce the complexity of drawing operations. For instance,
4016     * when animating a complex view tree with a translation, a hardware layer can
4017     * be used to render the view tree only once.</p>
4018     * <p>A hardware layer can also be used to increase the rendering quality when
4019     * rotation transformations are applied on a view. It can also be used to
4020     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4021     *
4022     * @see #getLayerType()
4023     * @see #setLayerType(int, android.graphics.Paint)
4024     * @see #LAYER_TYPE_NONE
4025     * @see #LAYER_TYPE_SOFTWARE
4026     */
4027    public static final int LAYER_TYPE_HARDWARE = 2;
4028
4029    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4030            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4031            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4032            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4033    })
4034    int mLayerType = LAYER_TYPE_NONE;
4035    Paint mLayerPaint;
4036
4037    /**
4038     * Set to true when drawing cache is enabled and cannot be created.
4039     *
4040     * @hide
4041     */
4042    public boolean mCachingFailed;
4043    private Bitmap mDrawingCache;
4044    private Bitmap mUnscaledDrawingCache;
4045
4046    /**
4047     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4048     * <p>
4049     * When non-null and valid, this is expected to contain an up-to-date copy
4050     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4051     * cleanup.
4052     */
4053    final RenderNode mRenderNode;
4054
4055    /**
4056     * Set to true when the view is sending hover accessibility events because it
4057     * is the innermost hovered view.
4058     */
4059    private boolean mSendingHoverAccessibilityEvents;
4060
4061    /**
4062     * Delegate for injecting accessibility functionality.
4063     */
4064    AccessibilityDelegate mAccessibilityDelegate;
4065
4066    /**
4067     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4068     * and add/remove objects to/from the overlay directly through the Overlay methods.
4069     */
4070    ViewOverlay mOverlay;
4071
4072    /**
4073     * The currently active parent view for receiving delegated nested scrolling events.
4074     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4075     * by {@link #stopNestedScroll()} at the same point where we clear
4076     * requestDisallowInterceptTouchEvent.
4077     */
4078    private ViewParent mNestedScrollingParent;
4079
4080    /**
4081     * Consistency verifier for debugging purposes.
4082     * @hide
4083     */
4084    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4085            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4086                    new InputEventConsistencyVerifier(this, 0) : null;
4087
4088    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4089
4090    private int[] mTempNestedScrollConsumed;
4091
4092    /**
4093     * An overlay is going to draw this View instead of being drawn as part of this
4094     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4095     * when this view is invalidated.
4096     */
4097    GhostView mGhostView;
4098
4099    /**
4100     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4101     * @hide
4102     */
4103    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4104    public String[] mAttributes;
4105
4106    /**
4107     * Maps a Resource id to its name.
4108     */
4109    private static SparseArray<String> mAttributeMap;
4110
4111    /**
4112     * Queue of pending runnables. Used to postpone calls to post() until this
4113     * view is attached and has a handler.
4114     */
4115    private HandlerActionQueue mRunQueue;
4116
4117    /**
4118     * The pointer icon when the mouse hovers on this view. The default is null.
4119     */
4120    private PointerIcon mPointerIcon;
4121
4122    /**
4123     * @hide
4124     */
4125    String mStartActivityRequestWho;
4126
4127    @Nullable
4128    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4129
4130    /**
4131     * Simple constructor to use when creating a view from code.
4132     *
4133     * @param context The Context the view is running in, through which it can
4134     *        access the current theme, resources, etc.
4135     */
4136    public View(Context context) {
4137        mContext = context;
4138        mResources = context != null ? context.getResources() : null;
4139        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4140        // Set some flags defaults
4141        mPrivateFlags2 =
4142                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4143                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4144                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4145                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4146                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4147                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4148        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4149        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4150        mUserPaddingStart = UNDEFINED_PADDING;
4151        mUserPaddingEnd = UNDEFINED_PADDING;
4152        mRenderNode = RenderNode.create(getClass().getName(), this);
4153
4154        if (!sCompatibilityDone && context != null) {
4155            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4156
4157            // Older apps may need this compatibility hack for measurement.
4158            sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4159
4160            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4161            // of whether a layout was requested on that View.
4162            sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4163
4164            Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4165
4166            // In M and newer, our widgets can pass a "hint" value in the size
4167            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4168            // know what the expected parent size is going to be, so e.g. list items can size
4169            // themselves at 1/3 the size of their container. It breaks older apps though,
4170            // specifically apps that use some popular open source libraries.
4171            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4172
4173            // Old versions of the platform would give different results from
4174            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4175            // modes, so we always need to run an additional EXACTLY pass.
4176            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4177
4178            // Prior to N, layout params could change without requiring a
4179            // subsequent call to setLayoutParams() and they would usually
4180            // work. Partial layout breaks this assumption.
4181            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4182
4183            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4184            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4185            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4186
4187            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4188            // in apps so we target check it to avoid breaking existing apps.
4189            sPreserveMarginParamsInLayoutParamConversion =
4190                    targetSdkVersion >= Build.VERSION_CODES.N;
4191
4192            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4193
4194            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4195
4196            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4197
4198            sCompatibilityDone = true;
4199        }
4200    }
4201
4202    /**
4203     * Constructor that is called when inflating a view from XML. This is called
4204     * when a view is being constructed from an XML file, supplying attributes
4205     * that were specified in the XML file. This version uses a default style of
4206     * 0, so the only attribute values applied are those in the Context's Theme
4207     * and the given AttributeSet.
4208     *
4209     * <p>
4210     * The method onFinishInflate() will be called after all children have been
4211     * added.
4212     *
4213     * @param context The Context the view is running in, through which it can
4214     *        access the current theme, resources, etc.
4215     * @param attrs The attributes of the XML tag that is inflating the view.
4216     * @see #View(Context, AttributeSet, int)
4217     */
4218    public View(Context context, @Nullable AttributeSet attrs) {
4219        this(context, attrs, 0);
4220    }
4221
4222    /**
4223     * Perform inflation from XML and apply a class-specific base style from a
4224     * theme attribute. This constructor of View allows subclasses to use their
4225     * own base style when they are inflating. For example, a Button class's
4226     * constructor would call this version of the super class constructor and
4227     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4228     * allows the theme's button style to modify all of the base view attributes
4229     * (in particular its background) as well as the Button class's attributes.
4230     *
4231     * @param context The Context the view is running in, through which it can
4232     *        access the current theme, resources, etc.
4233     * @param attrs The attributes of the XML tag that is inflating the view.
4234     * @param defStyleAttr An attribute in the current theme that contains a
4235     *        reference to a style resource that supplies default values for
4236     *        the view. Can be 0 to not look for defaults.
4237     * @see #View(Context, AttributeSet)
4238     */
4239    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4240        this(context, attrs, defStyleAttr, 0);
4241    }
4242
4243    /**
4244     * Perform inflation from XML and apply a class-specific base style from a
4245     * theme attribute or style resource. This constructor of View allows
4246     * subclasses to use their own base style when they are inflating.
4247     * <p>
4248     * When determining the final value of a particular attribute, there are
4249     * four inputs that come into play:
4250     * <ol>
4251     * <li>Any attribute values in the given AttributeSet.
4252     * <li>The style resource specified in the AttributeSet (named "style").
4253     * <li>The default style specified by <var>defStyleAttr</var>.
4254     * <li>The default style specified by <var>defStyleRes</var>.
4255     * <li>The base values in this theme.
4256     * </ol>
4257     * <p>
4258     * Each of these inputs is considered in-order, with the first listed taking
4259     * precedence over the following ones. In other words, if in the
4260     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4261     * , then the button's text will <em>always</em> be black, regardless of
4262     * what is specified in any of the styles.
4263     *
4264     * @param context The Context the view is running in, through which it can
4265     *        access the current theme, resources, etc.
4266     * @param attrs The attributes of the XML tag that is inflating the view.
4267     * @param defStyleAttr An attribute in the current theme that contains a
4268     *        reference to a style resource that supplies default values for
4269     *        the view. Can be 0 to not look for defaults.
4270     * @param defStyleRes A resource identifier of a style resource that
4271     *        supplies default values for the view, used only if
4272     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4273     *        to not look for defaults.
4274     * @see #View(Context, AttributeSet, int)
4275     */
4276    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4277        this(context);
4278
4279        final TypedArray a = context.obtainStyledAttributes(
4280                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4281
4282        if (mDebugViewAttributes) {
4283            saveAttributeData(attrs, a);
4284        }
4285
4286        Drawable background = null;
4287
4288        int leftPadding = -1;
4289        int topPadding = -1;
4290        int rightPadding = -1;
4291        int bottomPadding = -1;
4292        int startPadding = UNDEFINED_PADDING;
4293        int endPadding = UNDEFINED_PADDING;
4294
4295        int padding = -1;
4296        int paddingHorizontal = -1;
4297        int paddingVertical = -1;
4298
4299        int viewFlagValues = 0;
4300        int viewFlagMasks = 0;
4301
4302        boolean setScrollContainer = false;
4303
4304        int x = 0;
4305        int y = 0;
4306
4307        float tx = 0;
4308        float ty = 0;
4309        float tz = 0;
4310        float elevation = 0;
4311        float rotation = 0;
4312        float rotationX = 0;
4313        float rotationY = 0;
4314        float sx = 1f;
4315        float sy = 1f;
4316        boolean transformSet = false;
4317
4318        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4319        int overScrollMode = mOverScrollMode;
4320        boolean initializeScrollbars = false;
4321        boolean initializeScrollIndicators = false;
4322
4323        boolean startPaddingDefined = false;
4324        boolean endPaddingDefined = false;
4325        boolean leftPaddingDefined = false;
4326        boolean rightPaddingDefined = false;
4327
4328        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4329
4330        // Set default values.
4331        viewFlagValues |= FOCUSABLE_AUTO;
4332        viewFlagMasks |= FOCUSABLE_AUTO;
4333
4334        final int N = a.getIndexCount();
4335        for (int i = 0; i < N; i++) {
4336            int attr = a.getIndex(i);
4337            switch (attr) {
4338                case com.android.internal.R.styleable.View_background:
4339                    background = a.getDrawable(attr);
4340                    break;
4341                case com.android.internal.R.styleable.View_padding:
4342                    padding = a.getDimensionPixelSize(attr, -1);
4343                    mUserPaddingLeftInitial = padding;
4344                    mUserPaddingRightInitial = padding;
4345                    leftPaddingDefined = true;
4346                    rightPaddingDefined = true;
4347                    break;
4348                case com.android.internal.R.styleable.View_paddingHorizontal:
4349                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4350                    mUserPaddingLeftInitial = paddingHorizontal;
4351                    mUserPaddingRightInitial = paddingHorizontal;
4352                    leftPaddingDefined = true;
4353                    rightPaddingDefined = true;
4354                    break;
4355                case com.android.internal.R.styleable.View_paddingVertical:
4356                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4357                    break;
4358                 case com.android.internal.R.styleable.View_paddingLeft:
4359                    leftPadding = a.getDimensionPixelSize(attr, -1);
4360                    mUserPaddingLeftInitial = leftPadding;
4361                    leftPaddingDefined = true;
4362                    break;
4363                case com.android.internal.R.styleable.View_paddingTop:
4364                    topPadding = a.getDimensionPixelSize(attr, -1);
4365                    break;
4366                case com.android.internal.R.styleable.View_paddingRight:
4367                    rightPadding = a.getDimensionPixelSize(attr, -1);
4368                    mUserPaddingRightInitial = rightPadding;
4369                    rightPaddingDefined = true;
4370                    break;
4371                case com.android.internal.R.styleable.View_paddingBottom:
4372                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4373                    break;
4374                case com.android.internal.R.styleable.View_paddingStart:
4375                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4376                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4377                    break;
4378                case com.android.internal.R.styleable.View_paddingEnd:
4379                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4380                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4381                    break;
4382                case com.android.internal.R.styleable.View_scrollX:
4383                    x = a.getDimensionPixelOffset(attr, 0);
4384                    break;
4385                case com.android.internal.R.styleable.View_scrollY:
4386                    y = a.getDimensionPixelOffset(attr, 0);
4387                    break;
4388                case com.android.internal.R.styleable.View_alpha:
4389                    setAlpha(a.getFloat(attr, 1f));
4390                    break;
4391                case com.android.internal.R.styleable.View_transformPivotX:
4392                    setPivotX(a.getDimension(attr, 0));
4393                    break;
4394                case com.android.internal.R.styleable.View_transformPivotY:
4395                    setPivotY(a.getDimension(attr, 0));
4396                    break;
4397                case com.android.internal.R.styleable.View_translationX:
4398                    tx = a.getDimension(attr, 0);
4399                    transformSet = true;
4400                    break;
4401                case com.android.internal.R.styleable.View_translationY:
4402                    ty = a.getDimension(attr, 0);
4403                    transformSet = true;
4404                    break;
4405                case com.android.internal.R.styleable.View_translationZ:
4406                    tz = a.getDimension(attr, 0);
4407                    transformSet = true;
4408                    break;
4409                case com.android.internal.R.styleable.View_elevation:
4410                    elevation = a.getDimension(attr, 0);
4411                    transformSet = true;
4412                    break;
4413                case com.android.internal.R.styleable.View_rotation:
4414                    rotation = a.getFloat(attr, 0);
4415                    transformSet = true;
4416                    break;
4417                case com.android.internal.R.styleable.View_rotationX:
4418                    rotationX = a.getFloat(attr, 0);
4419                    transformSet = true;
4420                    break;
4421                case com.android.internal.R.styleable.View_rotationY:
4422                    rotationY = a.getFloat(attr, 0);
4423                    transformSet = true;
4424                    break;
4425                case com.android.internal.R.styleable.View_scaleX:
4426                    sx = a.getFloat(attr, 1f);
4427                    transformSet = true;
4428                    break;
4429                case com.android.internal.R.styleable.View_scaleY:
4430                    sy = a.getFloat(attr, 1f);
4431                    transformSet = true;
4432                    break;
4433                case com.android.internal.R.styleable.View_id:
4434                    mID = a.getResourceId(attr, NO_ID);
4435                    break;
4436                case com.android.internal.R.styleable.View_tag:
4437                    mTag = a.getText(attr);
4438                    break;
4439                case com.android.internal.R.styleable.View_fitsSystemWindows:
4440                    if (a.getBoolean(attr, false)) {
4441                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4442                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4443                    }
4444                    break;
4445                case com.android.internal.R.styleable.View_focusable:
4446                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4447                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4448                        viewFlagMasks |= FOCUSABLE_MASK;
4449                    }
4450                    break;
4451                case com.android.internal.R.styleable.View_focusableInTouchMode:
4452                    if (a.getBoolean(attr, false)) {
4453                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4454                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4455                    }
4456                    break;
4457                case com.android.internal.R.styleable.View_clickable:
4458                    if (a.getBoolean(attr, false)) {
4459                        viewFlagValues |= CLICKABLE;
4460                        viewFlagMasks |= CLICKABLE;
4461                    }
4462                    break;
4463                case com.android.internal.R.styleable.View_longClickable:
4464                    if (a.getBoolean(attr, false)) {
4465                        viewFlagValues |= LONG_CLICKABLE;
4466                        viewFlagMasks |= LONG_CLICKABLE;
4467                    }
4468                    break;
4469                case com.android.internal.R.styleable.View_contextClickable:
4470                    if (a.getBoolean(attr, false)) {
4471                        viewFlagValues |= CONTEXT_CLICKABLE;
4472                        viewFlagMasks |= CONTEXT_CLICKABLE;
4473                    }
4474                    break;
4475                case com.android.internal.R.styleable.View_saveEnabled:
4476                    if (!a.getBoolean(attr, true)) {
4477                        viewFlagValues |= SAVE_DISABLED;
4478                        viewFlagMasks |= SAVE_DISABLED_MASK;
4479                    }
4480                    break;
4481                case com.android.internal.R.styleable.View_duplicateParentState:
4482                    if (a.getBoolean(attr, false)) {
4483                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4484                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4485                    }
4486                    break;
4487                case com.android.internal.R.styleable.View_visibility:
4488                    final int visibility = a.getInt(attr, 0);
4489                    if (visibility != 0) {
4490                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4491                        viewFlagMasks |= VISIBILITY_MASK;
4492                    }
4493                    break;
4494                case com.android.internal.R.styleable.View_layoutDirection:
4495                    // Clear any layout direction flags (included resolved bits) already set
4496                    mPrivateFlags2 &=
4497                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4498                    // Set the layout direction flags depending on the value of the attribute
4499                    final int layoutDirection = a.getInt(attr, -1);
4500                    final int value = (layoutDirection != -1) ?
4501                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4502                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4503                    break;
4504                case com.android.internal.R.styleable.View_drawingCacheQuality:
4505                    final int cacheQuality = a.getInt(attr, 0);
4506                    if (cacheQuality != 0) {
4507                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4508                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4509                    }
4510                    break;
4511                case com.android.internal.R.styleable.View_contentDescription:
4512                    setContentDescription(a.getString(attr));
4513                    break;
4514                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4515                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4516                    break;
4517                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4518                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4519                    break;
4520                case com.android.internal.R.styleable.View_labelFor:
4521                    setLabelFor(a.getResourceId(attr, NO_ID));
4522                    break;
4523                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4524                    if (!a.getBoolean(attr, true)) {
4525                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4526                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4527                    }
4528                    break;
4529                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4530                    if (!a.getBoolean(attr, true)) {
4531                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4532                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4533                    }
4534                    break;
4535                case R.styleable.View_scrollbars:
4536                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4537                    if (scrollbars != SCROLLBARS_NONE) {
4538                        viewFlagValues |= scrollbars;
4539                        viewFlagMasks |= SCROLLBARS_MASK;
4540                        initializeScrollbars = true;
4541                    }
4542                    break;
4543                //noinspection deprecation
4544                case R.styleable.View_fadingEdge:
4545                    if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4546                        // Ignore the attribute starting with ICS
4547                        break;
4548                    }
4549                    // With builds < ICS, fall through and apply fading edges
4550                case R.styleable.View_requiresFadingEdge:
4551                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4552                    if (fadingEdge != FADING_EDGE_NONE) {
4553                        viewFlagValues |= fadingEdge;
4554                        viewFlagMasks |= FADING_EDGE_MASK;
4555                        initializeFadingEdgeInternal(a);
4556                    }
4557                    break;
4558                case R.styleable.View_scrollbarStyle:
4559                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4560                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4561                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4562                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4563                    }
4564                    break;
4565                case R.styleable.View_isScrollContainer:
4566                    setScrollContainer = true;
4567                    if (a.getBoolean(attr, false)) {
4568                        setScrollContainer(true);
4569                    }
4570                    break;
4571                case com.android.internal.R.styleable.View_keepScreenOn:
4572                    if (a.getBoolean(attr, false)) {
4573                        viewFlagValues |= KEEP_SCREEN_ON;
4574                        viewFlagMasks |= KEEP_SCREEN_ON;
4575                    }
4576                    break;
4577                case R.styleable.View_filterTouchesWhenObscured:
4578                    if (a.getBoolean(attr, false)) {
4579                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4580                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4581                    }
4582                    break;
4583                case R.styleable.View_nextFocusLeft:
4584                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4585                    break;
4586                case R.styleable.View_nextFocusRight:
4587                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4588                    break;
4589                case R.styleable.View_nextFocusUp:
4590                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4591                    break;
4592                case R.styleable.View_nextFocusDown:
4593                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4594                    break;
4595                case R.styleable.View_nextFocusForward:
4596                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4597                    break;
4598                case R.styleable.View_nextClusterForward:
4599                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4600                    break;
4601                case R.styleable.View_minWidth:
4602                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4603                    break;
4604                case R.styleable.View_minHeight:
4605                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4606                    break;
4607                case R.styleable.View_onClick:
4608                    if (context.isRestricted()) {
4609                        throw new IllegalStateException("The android:onClick attribute cannot "
4610                                + "be used within a restricted context");
4611                    }
4612
4613                    final String handlerName = a.getString(attr);
4614                    if (handlerName != null) {
4615                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4616                    }
4617                    break;
4618                case R.styleable.View_overScrollMode:
4619                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4620                    break;
4621                case R.styleable.View_verticalScrollbarPosition:
4622                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4623                    break;
4624                case R.styleable.View_layerType:
4625                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4626                    break;
4627                case R.styleable.View_textDirection:
4628                    // Clear any text direction flag already set
4629                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4630                    // Set the text direction flags depending on the value of the attribute
4631                    final int textDirection = a.getInt(attr, -1);
4632                    if (textDirection != -1) {
4633                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4634                    }
4635                    break;
4636                case R.styleable.View_textAlignment:
4637                    // Clear any text alignment flag already set
4638                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4639                    // Set the text alignment flag depending on the value of the attribute
4640                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4641                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4642                    break;
4643                case R.styleable.View_importantForAccessibility:
4644                    setImportantForAccessibility(a.getInt(attr,
4645                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4646                    break;
4647                case R.styleable.View_accessibilityLiveRegion:
4648                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4649                    break;
4650                case R.styleable.View_transitionName:
4651                    setTransitionName(a.getString(attr));
4652                    break;
4653                case R.styleable.View_nestedScrollingEnabled:
4654                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4655                    break;
4656                case R.styleable.View_stateListAnimator:
4657                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4658                            a.getResourceId(attr, 0)));
4659                    break;
4660                case R.styleable.View_backgroundTint:
4661                    // This will get applied later during setBackground().
4662                    if (mBackgroundTint == null) {
4663                        mBackgroundTint = new TintInfo();
4664                    }
4665                    mBackgroundTint.mTintList = a.getColorStateList(
4666                            R.styleable.View_backgroundTint);
4667                    mBackgroundTint.mHasTintList = true;
4668                    break;
4669                case R.styleable.View_backgroundTintMode:
4670                    // This will get applied later during setBackground().
4671                    if (mBackgroundTint == null) {
4672                        mBackgroundTint = new TintInfo();
4673                    }
4674                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4675                            R.styleable.View_backgroundTintMode, -1), null);
4676                    mBackgroundTint.mHasTintMode = true;
4677                    break;
4678                case R.styleable.View_outlineProvider:
4679                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4680                            PROVIDER_BACKGROUND));
4681                    break;
4682                case R.styleable.View_foreground:
4683                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4684                        setForeground(a.getDrawable(attr));
4685                    }
4686                    break;
4687                case R.styleable.View_foregroundGravity:
4688                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4689                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4690                    }
4691                    break;
4692                case R.styleable.View_foregroundTintMode:
4693                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4694                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4695                    }
4696                    break;
4697                case R.styleable.View_foregroundTint:
4698                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4699                        setForegroundTintList(a.getColorStateList(attr));
4700                    }
4701                    break;
4702                case R.styleable.View_foregroundInsidePadding:
4703                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4704                        if (mForegroundInfo == null) {
4705                            mForegroundInfo = new ForegroundInfo();
4706                        }
4707                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4708                                mForegroundInfo.mInsidePadding);
4709                    }
4710                    break;
4711                case R.styleable.View_scrollIndicators:
4712                    final int scrollIndicators =
4713                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4714                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4715                    if (scrollIndicators != 0) {
4716                        mPrivateFlags3 |= scrollIndicators;
4717                        initializeScrollIndicators = true;
4718                    }
4719                    break;
4720                case R.styleable.View_pointerIcon:
4721                    final int resourceId = a.getResourceId(attr, 0);
4722                    if (resourceId != 0) {
4723                        setPointerIcon(PointerIcon.load(
4724                                context.getResources(), resourceId));
4725                    } else {
4726                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
4727                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
4728                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
4729                        }
4730                    }
4731                    break;
4732                case R.styleable.View_forceHasOverlappingRendering:
4733                    if (a.peekValue(attr) != null) {
4734                        forceHasOverlappingRendering(a.getBoolean(attr, true));
4735                    }
4736                    break;
4737                case R.styleable.View_tooltipText:
4738                    setTooltipText(a.getText(attr));
4739                    break;
4740                case R.styleable.View_keyboardNavigationCluster:
4741                    if (a.peekValue(attr) != null) {
4742                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
4743                    }
4744                    break;
4745                case R.styleable.View_focusedByDefault:
4746                    if (a.peekValue(attr) != null) {
4747                        setFocusedByDefault(a.getBoolean(attr, true));
4748                    }
4749                    break;
4750            }
4751        }
4752
4753        setOverScrollMode(overScrollMode);
4754
4755        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4756        // the resolved layout direction). Those cached values will be used later during padding
4757        // resolution.
4758        mUserPaddingStart = startPadding;
4759        mUserPaddingEnd = endPadding;
4760
4761        if (background != null) {
4762            setBackground(background);
4763        }
4764
4765        // setBackground above will record that padding is currently provided by the background.
4766        // If we have padding specified via xml, record that here instead and use it.
4767        mLeftPaddingDefined = leftPaddingDefined;
4768        mRightPaddingDefined = rightPaddingDefined;
4769
4770        if (padding >= 0) {
4771            leftPadding = padding;
4772            topPadding = padding;
4773            rightPadding = padding;
4774            bottomPadding = padding;
4775            mUserPaddingLeftInitial = padding;
4776            mUserPaddingRightInitial = padding;
4777        } else {
4778            if (paddingHorizontal >= 0) {
4779                leftPadding = paddingHorizontal;
4780                rightPadding = paddingHorizontal;
4781                mUserPaddingLeftInitial = paddingHorizontal;
4782                mUserPaddingRightInitial = paddingHorizontal;
4783            }
4784            if (paddingVertical >= 0) {
4785                topPadding = paddingVertical;
4786                bottomPadding = paddingVertical;
4787            }
4788        }
4789
4790        if (isRtlCompatibilityMode()) {
4791            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4792            // left / right padding are used if defined (meaning here nothing to do). If they are not
4793            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4794            // start / end and resolve them as left / right (layout direction is not taken into account).
4795            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4796            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4797            // defined.
4798            if (!mLeftPaddingDefined && startPaddingDefined) {
4799                leftPadding = startPadding;
4800            }
4801            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4802            if (!mRightPaddingDefined && endPaddingDefined) {
4803                rightPadding = endPadding;
4804            }
4805            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4806        } else {
4807            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4808            // values defined. Otherwise, left /right values are used.
4809            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4810            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4811            // defined.
4812            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4813
4814            if (mLeftPaddingDefined && !hasRelativePadding) {
4815                mUserPaddingLeftInitial = leftPadding;
4816            }
4817            if (mRightPaddingDefined && !hasRelativePadding) {
4818                mUserPaddingRightInitial = rightPadding;
4819            }
4820        }
4821
4822        internalSetPadding(
4823                mUserPaddingLeftInitial,
4824                topPadding >= 0 ? topPadding : mPaddingTop,
4825                mUserPaddingRightInitial,
4826                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4827
4828        if (viewFlagMasks != 0) {
4829            setFlags(viewFlagValues, viewFlagMasks);
4830        }
4831
4832        if (initializeScrollbars) {
4833            initializeScrollbarsInternal(a);
4834        }
4835
4836        if (initializeScrollIndicators) {
4837            initializeScrollIndicatorsInternal();
4838        }
4839
4840        a.recycle();
4841
4842        // Needs to be called after mViewFlags is set
4843        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4844            recomputePadding();
4845        }
4846
4847        if (x != 0 || y != 0) {
4848            scrollTo(x, y);
4849        }
4850
4851        if (transformSet) {
4852            setTranslationX(tx);
4853            setTranslationY(ty);
4854            setTranslationZ(tz);
4855            setElevation(elevation);
4856            setRotation(rotation);
4857            setRotationX(rotationX);
4858            setRotationY(rotationY);
4859            setScaleX(sx);
4860            setScaleY(sy);
4861        }
4862
4863        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4864            setScrollContainer(true);
4865        }
4866
4867        computeOpaqueFlags();
4868    }
4869
4870    /**
4871     * An implementation of OnClickListener that attempts to lazily load a
4872     * named click handling method from a parent or ancestor context.
4873     */
4874    private static class DeclaredOnClickListener implements OnClickListener {
4875        private final View mHostView;
4876        private final String mMethodName;
4877
4878        private Method mResolvedMethod;
4879        private Context mResolvedContext;
4880
4881        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4882            mHostView = hostView;
4883            mMethodName = methodName;
4884        }
4885
4886        @Override
4887        public void onClick(@NonNull View v) {
4888            if (mResolvedMethod == null) {
4889                resolveMethod(mHostView.getContext(), mMethodName);
4890            }
4891
4892            try {
4893                mResolvedMethod.invoke(mResolvedContext, v);
4894            } catch (IllegalAccessException e) {
4895                throw new IllegalStateException(
4896                        "Could not execute non-public method for android:onClick", e);
4897            } catch (InvocationTargetException e) {
4898                throw new IllegalStateException(
4899                        "Could not execute method for android:onClick", e);
4900            }
4901        }
4902
4903        @NonNull
4904        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4905            while (context != null) {
4906                try {
4907                    if (!context.isRestricted()) {
4908                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4909                        if (method != null) {
4910                            mResolvedMethod = method;
4911                            mResolvedContext = context;
4912                            return;
4913                        }
4914                    }
4915                } catch (NoSuchMethodException e) {
4916                    // Failed to find method, keep searching up the hierarchy.
4917                }
4918
4919                if (context instanceof ContextWrapper) {
4920                    context = ((ContextWrapper) context).getBaseContext();
4921                } else {
4922                    // Can't search up the hierarchy, null out and fail.
4923                    context = null;
4924                }
4925            }
4926
4927            final int id = mHostView.getId();
4928            final String idText = id == NO_ID ? "" : " with id '"
4929                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4930            throw new IllegalStateException("Could not find method " + mMethodName
4931                    + "(View) in a parent or ancestor Context for android:onClick "
4932                    + "attribute defined on view " + mHostView.getClass() + idText);
4933        }
4934    }
4935
4936    /**
4937     * Non-public constructor for use in testing
4938     */
4939    View() {
4940        mResources = null;
4941        mRenderNode = RenderNode.create(getClass().getName(), this);
4942    }
4943
4944    final boolean debugDraw() {
4945        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
4946    }
4947
4948    private static SparseArray<String> getAttributeMap() {
4949        if (mAttributeMap == null) {
4950            mAttributeMap = new SparseArray<>();
4951        }
4952        return mAttributeMap;
4953    }
4954
4955    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4956        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4957        final int indexCount = t.getIndexCount();
4958        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4959
4960        int i = 0;
4961
4962        // Store raw XML attributes.
4963        for (int j = 0; j < attrsCount; ++j) {
4964            attributes[i] = attrs.getAttributeName(j);
4965            attributes[i + 1] = attrs.getAttributeValue(j);
4966            i += 2;
4967        }
4968
4969        // Store resolved styleable attributes.
4970        final Resources res = t.getResources();
4971        final SparseArray<String> attributeMap = getAttributeMap();
4972        for (int j = 0; j < indexCount; ++j) {
4973            final int index = t.getIndex(j);
4974            if (!t.hasValueOrEmpty(index)) {
4975                // Value is undefined. Skip it.
4976                continue;
4977            }
4978
4979            final int resourceId = t.getResourceId(index, 0);
4980            if (resourceId == 0) {
4981                // Value is not a reference. Skip it.
4982                continue;
4983            }
4984
4985            String resourceName = attributeMap.get(resourceId);
4986            if (resourceName == null) {
4987                try {
4988                    resourceName = res.getResourceName(resourceId);
4989                } catch (Resources.NotFoundException e) {
4990                    resourceName = "0x" + Integer.toHexString(resourceId);
4991                }
4992                attributeMap.put(resourceId, resourceName);
4993            }
4994
4995            attributes[i] = resourceName;
4996            attributes[i + 1] = t.getString(index);
4997            i += 2;
4998        }
4999
5000        // Trim to fit contents.
5001        final String[] trimmed = new String[i];
5002        System.arraycopy(attributes, 0, trimmed, 0, i);
5003        mAttributes = trimmed;
5004    }
5005
5006    public String toString() {
5007        StringBuilder out = new StringBuilder(128);
5008        out.append(getClass().getName());
5009        out.append('{');
5010        out.append(Integer.toHexString(System.identityHashCode(this)));
5011        out.append(' ');
5012        switch (mViewFlags&VISIBILITY_MASK) {
5013            case VISIBLE: out.append('V'); break;
5014            case INVISIBLE: out.append('I'); break;
5015            case GONE: out.append('G'); break;
5016            default: out.append('.'); break;
5017        }
5018        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5019        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5020        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5021        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5022        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5023        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5024        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5025        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5026        out.append(' ');
5027        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5028        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5029        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5030        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5031            out.append('p');
5032        } else {
5033            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5034        }
5035        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5036        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5037        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5038        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5039        out.append(' ');
5040        out.append(mLeft);
5041        out.append(',');
5042        out.append(mTop);
5043        out.append('-');
5044        out.append(mRight);
5045        out.append(',');
5046        out.append(mBottom);
5047        final int id = getId();
5048        if (id != NO_ID) {
5049            out.append(" #");
5050            out.append(Integer.toHexString(id));
5051            final Resources r = mResources;
5052            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5053                try {
5054                    String pkgname;
5055                    switch (id&0xff000000) {
5056                        case 0x7f000000:
5057                            pkgname="app";
5058                            break;
5059                        case 0x01000000:
5060                            pkgname="android";
5061                            break;
5062                        default:
5063                            pkgname = r.getResourcePackageName(id);
5064                            break;
5065                    }
5066                    String typename = r.getResourceTypeName(id);
5067                    String entryname = r.getResourceEntryName(id);
5068                    out.append(" ");
5069                    out.append(pkgname);
5070                    out.append(":");
5071                    out.append(typename);
5072                    out.append("/");
5073                    out.append(entryname);
5074                } catch (Resources.NotFoundException e) {
5075                }
5076            }
5077        }
5078        out.append("}");
5079        return out.toString();
5080    }
5081
5082    /**
5083     * <p>
5084     * Initializes the fading edges from a given set of styled attributes. This
5085     * method should be called by subclasses that need fading edges and when an
5086     * instance of these subclasses is created programmatically rather than
5087     * being inflated from XML. This method is automatically called when the XML
5088     * is inflated.
5089     * </p>
5090     *
5091     * @param a the styled attributes set to initialize the fading edges from
5092     *
5093     * @removed
5094     */
5095    protected void initializeFadingEdge(TypedArray a) {
5096        // This method probably shouldn't have been included in the SDK to begin with.
5097        // It relies on 'a' having been initialized using an attribute filter array that is
5098        // not publicly available to the SDK. The old method has been renamed
5099        // to initializeFadingEdgeInternal and hidden for framework use only;
5100        // this one initializes using defaults to make it safe to call for apps.
5101
5102        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5103
5104        initializeFadingEdgeInternal(arr);
5105
5106        arr.recycle();
5107    }
5108
5109    /**
5110     * <p>
5111     * Initializes the fading edges from a given set of styled attributes. This
5112     * method should be called by subclasses that need fading edges and when an
5113     * instance of these subclasses is created programmatically rather than
5114     * being inflated from XML. This method is automatically called when the XML
5115     * is inflated.
5116     * </p>
5117     *
5118     * @param a the styled attributes set to initialize the fading edges from
5119     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5120     */
5121    protected void initializeFadingEdgeInternal(TypedArray a) {
5122        initScrollCache();
5123
5124        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5125                R.styleable.View_fadingEdgeLength,
5126                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5127    }
5128
5129    /**
5130     * Returns the size of the vertical faded edges used to indicate that more
5131     * content in this view is visible.
5132     *
5133     * @return The size in pixels of the vertical faded edge or 0 if vertical
5134     *         faded edges are not enabled for this view.
5135     * @attr ref android.R.styleable#View_fadingEdgeLength
5136     */
5137    public int getVerticalFadingEdgeLength() {
5138        if (isVerticalFadingEdgeEnabled()) {
5139            ScrollabilityCache cache = mScrollCache;
5140            if (cache != null) {
5141                return cache.fadingEdgeLength;
5142            }
5143        }
5144        return 0;
5145    }
5146
5147    /**
5148     * Set the size of the faded edge used to indicate that more content in this
5149     * view is available.  Will not change whether the fading edge is enabled; use
5150     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5151     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5152     * for the vertical or horizontal fading edges.
5153     *
5154     * @param length The size in pixels of the faded edge used to indicate that more
5155     *        content in this view is visible.
5156     */
5157    public void setFadingEdgeLength(int length) {
5158        initScrollCache();
5159        mScrollCache.fadingEdgeLength = length;
5160    }
5161
5162    /**
5163     * Returns the size of the horizontal faded edges used to indicate that more
5164     * content in this view is visible.
5165     *
5166     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5167     *         faded edges are not enabled for this view.
5168     * @attr ref android.R.styleable#View_fadingEdgeLength
5169     */
5170    public int getHorizontalFadingEdgeLength() {
5171        if (isHorizontalFadingEdgeEnabled()) {
5172            ScrollabilityCache cache = mScrollCache;
5173            if (cache != null) {
5174                return cache.fadingEdgeLength;
5175            }
5176        }
5177        return 0;
5178    }
5179
5180    /**
5181     * Returns the width of the vertical scrollbar.
5182     *
5183     * @return The width in pixels of the vertical scrollbar or 0 if there
5184     *         is no vertical scrollbar.
5185     */
5186    public int getVerticalScrollbarWidth() {
5187        ScrollabilityCache cache = mScrollCache;
5188        if (cache != null) {
5189            ScrollBarDrawable scrollBar = cache.scrollBar;
5190            if (scrollBar != null) {
5191                int size = scrollBar.getSize(true);
5192                if (size <= 0) {
5193                    size = cache.scrollBarSize;
5194                }
5195                return size;
5196            }
5197            return 0;
5198        }
5199        return 0;
5200    }
5201
5202    /**
5203     * Returns the height of the horizontal scrollbar.
5204     *
5205     * @return The height in pixels of the horizontal scrollbar or 0 if
5206     *         there is no horizontal scrollbar.
5207     */
5208    protected int getHorizontalScrollbarHeight() {
5209        ScrollabilityCache cache = mScrollCache;
5210        if (cache != null) {
5211            ScrollBarDrawable scrollBar = cache.scrollBar;
5212            if (scrollBar != null) {
5213                int size = scrollBar.getSize(false);
5214                if (size <= 0) {
5215                    size = cache.scrollBarSize;
5216                }
5217                return size;
5218            }
5219            return 0;
5220        }
5221        return 0;
5222    }
5223
5224    /**
5225     * <p>
5226     * Initializes the scrollbars from a given set of styled attributes. This
5227     * method should be called by subclasses that need scrollbars and when an
5228     * instance of these subclasses is created programmatically rather than
5229     * being inflated from XML. This method is automatically called when the XML
5230     * is inflated.
5231     * </p>
5232     *
5233     * @param a the styled attributes set to initialize the scrollbars from
5234     *
5235     * @removed
5236     */
5237    protected void initializeScrollbars(TypedArray a) {
5238        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5239        // using the View filter array which is not available to the SDK. As such, internal
5240        // framework usage now uses initializeScrollbarsInternal and we grab a default
5241        // TypedArray with the right filter instead here.
5242        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5243
5244        initializeScrollbarsInternal(arr);
5245
5246        // We ignored the method parameter. Recycle the one we actually did use.
5247        arr.recycle();
5248    }
5249
5250    /**
5251     * <p>
5252     * Initializes the scrollbars from a given set of styled attributes. This
5253     * method should be called by subclasses that need scrollbars and when an
5254     * instance of these subclasses is created programmatically rather than
5255     * being inflated from XML. This method is automatically called when the XML
5256     * is inflated.
5257     * </p>
5258     *
5259     * @param a the styled attributes set to initialize the scrollbars from
5260     * @hide
5261     */
5262    protected void initializeScrollbarsInternal(TypedArray a) {
5263        initScrollCache();
5264
5265        final ScrollabilityCache scrollabilityCache = mScrollCache;
5266
5267        if (scrollabilityCache.scrollBar == null) {
5268            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5269            scrollabilityCache.scrollBar.setState(getDrawableState());
5270            scrollabilityCache.scrollBar.setCallback(this);
5271        }
5272
5273        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5274
5275        if (!fadeScrollbars) {
5276            scrollabilityCache.state = ScrollabilityCache.ON;
5277        }
5278        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5279
5280
5281        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5282                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5283                        .getScrollBarFadeDuration());
5284        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5285                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5286                ViewConfiguration.getScrollDefaultDelay());
5287
5288
5289        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5290                com.android.internal.R.styleable.View_scrollbarSize,
5291                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5292
5293        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5294        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5295
5296        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5297        if (thumb != null) {
5298            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5299        }
5300
5301        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5302                false);
5303        if (alwaysDraw) {
5304            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5305        }
5306
5307        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5308        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5309
5310        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5311        if (thumb != null) {
5312            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5313        }
5314
5315        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5316                false);
5317        if (alwaysDraw) {
5318            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5319        }
5320
5321        // Apply layout direction to the new Drawables if needed
5322        final int layoutDirection = getLayoutDirection();
5323        if (track != null) {
5324            track.setLayoutDirection(layoutDirection);
5325        }
5326        if (thumb != null) {
5327            thumb.setLayoutDirection(layoutDirection);
5328        }
5329
5330        // Re-apply user/background padding so that scrollbar(s) get added
5331        resolvePadding();
5332    }
5333
5334    private void initializeScrollIndicatorsInternal() {
5335        // Some day maybe we'll break this into top/left/start/etc. and let the
5336        // client control it. Until then, you can have any scroll indicator you
5337        // want as long as it's a 1dp foreground-colored rectangle.
5338        if (mScrollIndicatorDrawable == null) {
5339            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5340        }
5341    }
5342
5343    /**
5344     * <p>
5345     * Initalizes the scrollability cache if necessary.
5346     * </p>
5347     */
5348    private void initScrollCache() {
5349        if (mScrollCache == null) {
5350            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5351        }
5352    }
5353
5354    private ScrollabilityCache getScrollCache() {
5355        initScrollCache();
5356        return mScrollCache;
5357    }
5358
5359    /**
5360     * Set the position of the vertical scroll bar. Should be one of
5361     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5362     * {@link #SCROLLBAR_POSITION_RIGHT}.
5363     *
5364     * @param position Where the vertical scroll bar should be positioned.
5365     */
5366    public void setVerticalScrollbarPosition(int position) {
5367        if (mVerticalScrollbarPosition != position) {
5368            mVerticalScrollbarPosition = position;
5369            computeOpaqueFlags();
5370            resolvePadding();
5371        }
5372    }
5373
5374    /**
5375     * @return The position where the vertical scroll bar will show, if applicable.
5376     * @see #setVerticalScrollbarPosition(int)
5377     */
5378    public int getVerticalScrollbarPosition() {
5379        return mVerticalScrollbarPosition;
5380    }
5381
5382    boolean isOnScrollbar(float x, float y) {
5383        if (mScrollCache == null) {
5384            return false;
5385        }
5386        x += getScrollX();
5387        y += getScrollY();
5388        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5389            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5390            getVerticalScrollBarBounds(null, touchBounds);
5391            if (touchBounds.contains((int) x, (int) y)) {
5392                return true;
5393            }
5394        }
5395        if (isHorizontalScrollBarEnabled()) {
5396            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5397            getHorizontalScrollBarBounds(null, touchBounds);
5398            if (touchBounds.contains((int) x, (int) y)) {
5399                return true;
5400            }
5401        }
5402        return false;
5403    }
5404
5405    boolean isOnScrollbarThumb(float x, float y) {
5406        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5407    }
5408
5409    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5410        if (mScrollCache == null) {
5411            return false;
5412        }
5413        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5414            x += getScrollX();
5415            y += getScrollY();
5416            final Rect bounds = mScrollCache.mScrollBarBounds;
5417            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5418            getVerticalScrollBarBounds(bounds, touchBounds);
5419            final int range = computeVerticalScrollRange();
5420            final int offset = computeVerticalScrollOffset();
5421            final int extent = computeVerticalScrollExtent();
5422            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5423                    extent, range);
5424            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5425                    extent, range, offset);
5426            final int thumbTop = bounds.top + thumbOffset;
5427            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5428            if (x >= touchBounds.left && x <= touchBounds.right
5429                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5430                return true;
5431            }
5432        }
5433        return false;
5434    }
5435
5436    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5437        if (mScrollCache == null) {
5438            return false;
5439        }
5440        if (isHorizontalScrollBarEnabled()) {
5441            x += getScrollX();
5442            y += getScrollY();
5443            final Rect bounds = mScrollCache.mScrollBarBounds;
5444            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5445            getHorizontalScrollBarBounds(bounds, touchBounds);
5446            final int range = computeHorizontalScrollRange();
5447            final int offset = computeHorizontalScrollOffset();
5448            final int extent = computeHorizontalScrollExtent();
5449            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5450                    extent, range);
5451            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5452                    extent, range, offset);
5453            final int thumbLeft = bounds.left + thumbOffset;
5454            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5455            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5456                    && y >= touchBounds.top && y <= touchBounds.bottom) {
5457                return true;
5458            }
5459        }
5460        return false;
5461    }
5462
5463    boolean isDraggingScrollBar() {
5464        return mScrollCache != null
5465                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5466    }
5467
5468    /**
5469     * Sets the state of all scroll indicators.
5470     * <p>
5471     * See {@link #setScrollIndicators(int, int)} for usage information.
5472     *
5473     * @param indicators a bitmask of indicators that should be enabled, or
5474     *                   {@code 0} to disable all indicators
5475     * @see #setScrollIndicators(int, int)
5476     * @see #getScrollIndicators()
5477     * @attr ref android.R.styleable#View_scrollIndicators
5478     */
5479    public void setScrollIndicators(@ScrollIndicators int indicators) {
5480        setScrollIndicators(indicators,
5481                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5482    }
5483
5484    /**
5485     * Sets the state of the scroll indicators specified by the mask. To change
5486     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5487     * <p>
5488     * When a scroll indicator is enabled, it will be displayed if the view
5489     * can scroll in the direction of the indicator.
5490     * <p>
5491     * Multiple indicator types may be enabled or disabled by passing the
5492     * logical OR of the desired types. If multiple types are specified, they
5493     * will all be set to the same enabled state.
5494     * <p>
5495     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5496     *
5497     * @param indicators the indicator direction, or the logical OR of multiple
5498     *             indicator directions. One or more of:
5499     *             <ul>
5500     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5501     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5502     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5503     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5504     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5505     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5506     *             </ul>
5507     * @see #setScrollIndicators(int)
5508     * @see #getScrollIndicators()
5509     * @attr ref android.R.styleable#View_scrollIndicators
5510     */
5511    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5512        // Shift and sanitize mask.
5513        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5514        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5515
5516        // Shift and mask indicators.
5517        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5518        indicators &= mask;
5519
5520        // Merge with non-masked flags.
5521        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5522
5523        if (mPrivateFlags3 != updatedFlags) {
5524            mPrivateFlags3 = updatedFlags;
5525
5526            if (indicators != 0) {
5527                initializeScrollIndicatorsInternal();
5528            }
5529            invalidate();
5530        }
5531    }
5532
5533    /**
5534     * Returns a bitmask representing the enabled scroll indicators.
5535     * <p>
5536     * For example, if the top and left scroll indicators are enabled and all
5537     * other indicators are disabled, the return value will be
5538     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5539     * <p>
5540     * To check whether the bottom scroll indicator is enabled, use the value
5541     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5542     *
5543     * @return a bitmask representing the enabled scroll indicators
5544     */
5545    @ScrollIndicators
5546    public int getScrollIndicators() {
5547        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5548                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5549    }
5550
5551    ListenerInfo getListenerInfo() {
5552        if (mListenerInfo != null) {
5553            return mListenerInfo;
5554        }
5555        mListenerInfo = new ListenerInfo();
5556        return mListenerInfo;
5557    }
5558
5559    /**
5560     * Register a callback to be invoked when the scroll X or Y positions of
5561     * this view change.
5562     * <p>
5563     * <b>Note:</b> Some views handle scrolling independently from View and may
5564     * have their own separate listeners for scroll-type events. For example,
5565     * {@link android.widget.ListView ListView} allows clients to register an
5566     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5567     * to listen for changes in list scroll position.
5568     *
5569     * @param l The listener to notify when the scroll X or Y position changes.
5570     * @see android.view.View#getScrollX()
5571     * @see android.view.View#getScrollY()
5572     */
5573    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5574        getListenerInfo().mOnScrollChangeListener = l;
5575    }
5576
5577    /**
5578     * Register a callback to be invoked when focus of this view changed.
5579     *
5580     * @param l The callback that will run.
5581     */
5582    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5583        getListenerInfo().mOnFocusChangeListener = l;
5584    }
5585
5586    /**
5587     * Add a listener that will be called when the bounds of the view change due to
5588     * layout processing.
5589     *
5590     * @param listener The listener that will be called when layout bounds change.
5591     */
5592    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5593        ListenerInfo li = getListenerInfo();
5594        if (li.mOnLayoutChangeListeners == null) {
5595            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5596        }
5597        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5598            li.mOnLayoutChangeListeners.add(listener);
5599        }
5600    }
5601
5602    /**
5603     * Remove a listener for layout changes.
5604     *
5605     * @param listener The listener for layout bounds change.
5606     */
5607    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5608        ListenerInfo li = mListenerInfo;
5609        if (li == null || li.mOnLayoutChangeListeners == null) {
5610            return;
5611        }
5612        li.mOnLayoutChangeListeners.remove(listener);
5613    }
5614
5615    /**
5616     * Add a listener for attach state changes.
5617     *
5618     * This listener will be called whenever this view is attached or detached
5619     * from a window. Remove the listener using
5620     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5621     *
5622     * @param listener Listener to attach
5623     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5624     */
5625    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5626        ListenerInfo li = getListenerInfo();
5627        if (li.mOnAttachStateChangeListeners == null) {
5628            li.mOnAttachStateChangeListeners
5629                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5630        }
5631        li.mOnAttachStateChangeListeners.add(listener);
5632    }
5633
5634    /**
5635     * Remove a listener for attach state changes. The listener will receive no further
5636     * notification of window attach/detach events.
5637     *
5638     * @param listener Listener to remove
5639     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5640     */
5641    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5642        ListenerInfo li = mListenerInfo;
5643        if (li == null || li.mOnAttachStateChangeListeners == null) {
5644            return;
5645        }
5646        li.mOnAttachStateChangeListeners.remove(listener);
5647    }
5648
5649    /**
5650     * Returns the focus-change callback registered for this view.
5651     *
5652     * @return The callback, or null if one is not registered.
5653     */
5654    public OnFocusChangeListener getOnFocusChangeListener() {
5655        ListenerInfo li = mListenerInfo;
5656        return li != null ? li.mOnFocusChangeListener : null;
5657    }
5658
5659    /**
5660     * Register a callback to be invoked when this view is clicked. If this view is not
5661     * clickable, it becomes clickable.
5662     *
5663     * @param l The callback that will run
5664     *
5665     * @see #setClickable(boolean)
5666     */
5667    public void setOnClickListener(@Nullable OnClickListener l) {
5668        if (!isClickable()) {
5669            setClickable(true);
5670        }
5671        getListenerInfo().mOnClickListener = l;
5672    }
5673
5674    /**
5675     * Return whether this view has an attached OnClickListener.  Returns
5676     * true if there is a listener, false if there is none.
5677     */
5678    public boolean hasOnClickListeners() {
5679        ListenerInfo li = mListenerInfo;
5680        return (li != null && li.mOnClickListener != null);
5681    }
5682
5683    /**
5684     * Register a callback to be invoked when this view is clicked and held. If this view is not
5685     * long clickable, it becomes long clickable.
5686     *
5687     * @param l The callback that will run
5688     *
5689     * @see #setLongClickable(boolean)
5690     */
5691    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5692        if (!isLongClickable()) {
5693            setLongClickable(true);
5694        }
5695        getListenerInfo().mOnLongClickListener = l;
5696    }
5697
5698    /**
5699     * Register a callback to be invoked when this view is context clicked. If the view is not
5700     * context clickable, it becomes context clickable.
5701     *
5702     * @param l The callback that will run
5703     * @see #setContextClickable(boolean)
5704     */
5705    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5706        if (!isContextClickable()) {
5707            setContextClickable(true);
5708        }
5709        getListenerInfo().mOnContextClickListener = l;
5710    }
5711
5712    /**
5713     * Register a callback to be invoked when the context menu for this view is
5714     * being built. If this view is not long clickable, it becomes long clickable.
5715     *
5716     * @param l The callback that will run
5717     *
5718     */
5719    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5720        if (!isLongClickable()) {
5721            setLongClickable(true);
5722        }
5723        getListenerInfo().mOnCreateContextMenuListener = l;
5724    }
5725
5726    /**
5727     * Set an observer to collect stats for each frame rendered for this view.
5728     *
5729     * @hide
5730     */
5731    public void addFrameMetricsListener(Window window,
5732            Window.OnFrameMetricsAvailableListener listener,
5733            Handler handler) {
5734        if (mAttachInfo != null) {
5735            if (mAttachInfo.mThreadedRenderer != null) {
5736                if (mFrameMetricsObservers == null) {
5737                    mFrameMetricsObservers = new ArrayList<>();
5738                }
5739
5740                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5741                        handler.getLooper(), listener);
5742                mFrameMetricsObservers.add(fmo);
5743                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
5744            } else {
5745                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5746            }
5747        } else {
5748            if (mFrameMetricsObservers == null) {
5749                mFrameMetricsObservers = new ArrayList<>();
5750            }
5751
5752            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
5753                    handler.getLooper(), listener);
5754            mFrameMetricsObservers.add(fmo);
5755        }
5756    }
5757
5758    /**
5759     * Remove observer configured to collect frame stats for this view.
5760     *
5761     * @hide
5762     */
5763    public void removeFrameMetricsListener(
5764            Window.OnFrameMetricsAvailableListener listener) {
5765        ThreadedRenderer renderer = getThreadedRenderer();
5766        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
5767        if (fmo == null) {
5768            throw new IllegalArgumentException(
5769                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
5770        }
5771
5772        if (mFrameMetricsObservers != null) {
5773            mFrameMetricsObservers.remove(fmo);
5774            if (renderer != null) {
5775                renderer.removeFrameMetricsObserver(fmo);
5776            }
5777        }
5778    }
5779
5780    private void registerPendingFrameMetricsObservers() {
5781        if (mFrameMetricsObservers != null) {
5782            ThreadedRenderer renderer = getThreadedRenderer();
5783            if (renderer != null) {
5784                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
5785                    renderer.addFrameMetricsObserver(fmo);
5786                }
5787            } else {
5788                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
5789            }
5790        }
5791    }
5792
5793    private FrameMetricsObserver findFrameMetricsObserver(
5794            Window.OnFrameMetricsAvailableListener listener) {
5795        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
5796            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
5797            if (observer.mListener == listener) {
5798                return observer;
5799            }
5800        }
5801
5802        return null;
5803    }
5804
5805    /**
5806     * Call this view's OnClickListener, if it is defined.  Performs all normal
5807     * actions associated with clicking: reporting accessibility event, playing
5808     * a sound, etc.
5809     *
5810     * @return True there was an assigned OnClickListener that was called, false
5811     *         otherwise is returned.
5812     */
5813    public boolean performClick() {
5814        final boolean result;
5815        final ListenerInfo li = mListenerInfo;
5816        if (li != null && li.mOnClickListener != null) {
5817            playSoundEffect(SoundEffectConstants.CLICK);
5818            li.mOnClickListener.onClick(this);
5819            result = true;
5820        } else {
5821            result = false;
5822        }
5823
5824        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5825        return result;
5826    }
5827
5828    /**
5829     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5830     * this only calls the listener, and does not do any associated clicking
5831     * actions like reporting an accessibility event.
5832     *
5833     * @return True there was an assigned OnClickListener that was called, false
5834     *         otherwise is returned.
5835     */
5836    public boolean callOnClick() {
5837        ListenerInfo li = mListenerInfo;
5838        if (li != null && li.mOnClickListener != null) {
5839            li.mOnClickListener.onClick(this);
5840            return true;
5841        }
5842        return false;
5843    }
5844
5845    /**
5846     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5847     * context menu if the OnLongClickListener did not consume the event.
5848     *
5849     * @return {@code true} if one of the above receivers consumed the event,
5850     *         {@code false} otherwise
5851     */
5852    public boolean performLongClick() {
5853        return performLongClickInternal(mLongClickX, mLongClickY);
5854    }
5855
5856    /**
5857     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5858     * context menu if the OnLongClickListener did not consume the event,
5859     * anchoring it to an (x,y) coordinate.
5860     *
5861     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5862     *          to disable anchoring
5863     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5864     *          to disable anchoring
5865     * @return {@code true} if one of the above receivers consumed the event,
5866     *         {@code false} otherwise
5867     */
5868    public boolean performLongClick(float x, float y) {
5869        mLongClickX = x;
5870        mLongClickY = y;
5871        final boolean handled = performLongClick();
5872        mLongClickX = Float.NaN;
5873        mLongClickY = Float.NaN;
5874        return handled;
5875    }
5876
5877    /**
5878     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5879     * context menu if the OnLongClickListener did not consume the event,
5880     * optionally anchoring it to an (x,y) coordinate.
5881     *
5882     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5883     *          to disable anchoring
5884     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5885     *          to disable anchoring
5886     * @return {@code true} if one of the above receivers consumed the event,
5887     *         {@code false} otherwise
5888     */
5889    private boolean performLongClickInternal(float x, float y) {
5890        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5891
5892        boolean handled = false;
5893        final ListenerInfo li = mListenerInfo;
5894        if (li != null && li.mOnLongClickListener != null) {
5895            handled = li.mOnLongClickListener.onLongClick(View.this);
5896        }
5897        if (!handled) {
5898            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5899            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5900        }
5901        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
5902            if (!handled) {
5903                handled = showLongClickTooltip((int) x, (int) y);
5904            }
5905        }
5906        if (handled) {
5907            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5908        }
5909        return handled;
5910    }
5911
5912    /**
5913     * Call this view's OnContextClickListener, if it is defined.
5914     *
5915     * @param x the x coordinate of the context click
5916     * @param y the y coordinate of the context click
5917     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5918     *         otherwise.
5919     */
5920    public boolean performContextClick(float x, float y) {
5921        return performContextClick();
5922    }
5923
5924    /**
5925     * Call this view's OnContextClickListener, if it is defined.
5926     *
5927     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5928     *         otherwise.
5929     */
5930    public boolean performContextClick() {
5931        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5932
5933        boolean handled = false;
5934        ListenerInfo li = mListenerInfo;
5935        if (li != null && li.mOnContextClickListener != null) {
5936            handled = li.mOnContextClickListener.onContextClick(View.this);
5937        }
5938        if (handled) {
5939            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5940        }
5941        return handled;
5942    }
5943
5944    /**
5945     * Performs button-related actions during a touch down event.
5946     *
5947     * @param event The event.
5948     * @return True if the down was consumed.
5949     *
5950     * @hide
5951     */
5952    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5953        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5954            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5955            showContextMenu(event.getX(), event.getY());
5956            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5957            return true;
5958        }
5959        return false;
5960    }
5961
5962    /**
5963     * Shows the context menu for this view.
5964     *
5965     * @return {@code true} if the context menu was shown, {@code false}
5966     *         otherwise
5967     * @see #showContextMenu(float, float)
5968     */
5969    public boolean showContextMenu() {
5970        return getParent().showContextMenuForChild(this);
5971    }
5972
5973    /**
5974     * Shows the context menu for this view anchored to the specified
5975     * view-relative coordinate.
5976     *
5977     * @param x the X coordinate in pixels relative to the view to which the
5978     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5979     * @param y the Y coordinate in pixels relative to the view to which the
5980     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
5981     * @return {@code true} if the context menu was shown, {@code false}
5982     *         otherwise
5983     */
5984    public boolean showContextMenu(float x, float y) {
5985        return getParent().showContextMenuForChild(this, x, y);
5986    }
5987
5988    /**
5989     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5990     *
5991     * @param callback Callback that will control the lifecycle of the action mode
5992     * @return The new action mode if it is started, null otherwise
5993     *
5994     * @see ActionMode
5995     * @see #startActionMode(android.view.ActionMode.Callback, int)
5996     */
5997    public ActionMode startActionMode(ActionMode.Callback callback) {
5998        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5999    }
6000
6001    /**
6002     * Start an action mode with the given type.
6003     *
6004     * @param callback Callback that will control the lifecycle of the action mode
6005     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6006     * @return The new action mode if it is started, null otherwise
6007     *
6008     * @see ActionMode
6009     */
6010    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6011        ViewParent parent = getParent();
6012        if (parent == null) return null;
6013        try {
6014            return parent.startActionModeForChild(this, callback, type);
6015        } catch (AbstractMethodError ame) {
6016            // Older implementations of custom views might not implement this.
6017            return parent.startActionModeForChild(this, callback);
6018        }
6019    }
6020
6021    /**
6022     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6023     * Context, creating a unique View identifier to retrieve the result.
6024     *
6025     * @param intent The Intent to be started.
6026     * @param requestCode The request code to use.
6027     * @hide
6028     */
6029    public void startActivityForResult(Intent intent, int requestCode) {
6030        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6031        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6032    }
6033
6034    /**
6035     * If this View corresponds to the calling who, dispatches the activity result.
6036     * @param who The identifier for the targeted View to receive the result.
6037     * @param requestCode The integer request code originally supplied to
6038     *                    startActivityForResult(), allowing you to identify who this
6039     *                    result came from.
6040     * @param resultCode The integer result code returned by the child activity
6041     *                   through its setResult().
6042     * @param data An Intent, which can return result data to the caller
6043     *               (various data can be attached to Intent "extras").
6044     * @return {@code true} if the activity result was dispatched.
6045     * @hide
6046     */
6047    public boolean dispatchActivityResult(
6048            String who, int requestCode, int resultCode, Intent data) {
6049        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6050            onActivityResult(requestCode, resultCode, data);
6051            mStartActivityRequestWho = null;
6052            return true;
6053        }
6054        return false;
6055    }
6056
6057    /**
6058     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6059     *
6060     * @param requestCode The integer request code originally supplied to
6061     *                    startActivityForResult(), allowing you to identify who this
6062     *                    result came from.
6063     * @param resultCode The integer result code returned by the child activity
6064     *                   through its setResult().
6065     * @param data An Intent, which can return result data to the caller
6066     *               (various data can be attached to Intent "extras").
6067     * @hide
6068     */
6069    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6070        // Do nothing.
6071    }
6072
6073    /**
6074     * Register a callback to be invoked when a hardware key is pressed in this view.
6075     * Key presses in software input methods will generally not trigger the methods of
6076     * this listener.
6077     * @param l the key listener to attach to this view
6078     */
6079    public void setOnKeyListener(OnKeyListener l) {
6080        getListenerInfo().mOnKeyListener = l;
6081    }
6082
6083    /**
6084     * Register a callback to be invoked when a touch event is sent to this view.
6085     * @param l the touch listener to attach to this view
6086     */
6087    public void setOnTouchListener(OnTouchListener l) {
6088        getListenerInfo().mOnTouchListener = l;
6089    }
6090
6091    /**
6092     * Register a callback to be invoked when a generic motion event is sent to this view.
6093     * @param l the generic motion listener to attach to this view
6094     */
6095    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6096        getListenerInfo().mOnGenericMotionListener = l;
6097    }
6098
6099    /**
6100     * Register a callback to be invoked when a hover event is sent to this view.
6101     * @param l the hover listener to attach to this view
6102     */
6103    public void setOnHoverListener(OnHoverListener l) {
6104        getListenerInfo().mOnHoverListener = l;
6105    }
6106
6107    /**
6108     * Register a drag event listener callback object for this View. The parameter is
6109     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6110     * View, the system calls the
6111     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6112     * @param l An implementation of {@link android.view.View.OnDragListener}.
6113     */
6114    public void setOnDragListener(OnDragListener l) {
6115        getListenerInfo().mOnDragListener = l;
6116    }
6117
6118    /**
6119     * Give this view focus. This will cause
6120     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6121     *
6122     * Note: this does not check whether this {@link View} should get focus, it just
6123     * gives it focus no matter what.  It should only be called internally by framework
6124     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6125     *
6126     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6127     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6128     *        focus moved when requestFocus() is called. It may not always
6129     *        apply, in which case use the default View.FOCUS_DOWN.
6130     * @param previouslyFocusedRect The rectangle of the view that had focus
6131     *        prior in this View's coordinate system.
6132     */
6133    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6134        if (DBG) {
6135            System.out.println(this + " requestFocus()");
6136        }
6137
6138        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6139            mPrivateFlags |= PFLAG_FOCUSED;
6140
6141            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6142
6143            if (mParent != null) {
6144                mParent.requestChildFocus(this, this);
6145                setFocusedInCluster();
6146            }
6147
6148            if (mAttachInfo != null) {
6149                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6150            }
6151
6152            onFocusChanged(true, direction, previouslyFocusedRect);
6153            refreshDrawableState();
6154        }
6155    }
6156
6157    /**
6158     * Sets this view's preference for reveal behavior when it gains focus.
6159     *
6160     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6161     * this view would prefer to be brought fully into view when it gains focus.
6162     * For example, a text field that a user is meant to type into. Other views such
6163     * as scrolling containers may prefer to opt-out of this behavior.</p>
6164     *
6165     * <p>The default value for views is true, though subclasses may change this
6166     * based on their preferred behavior.</p>
6167     *
6168     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6169     *
6170     * @see #getRevealOnFocusHint()
6171     */
6172    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6173        if (revealOnFocus) {
6174            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6175        } else {
6176            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6177        }
6178    }
6179
6180    /**
6181     * Returns this view's preference for reveal behavior when it gains focus.
6182     *
6183     * <p>When this method returns true for a child view requesting focus, ancestor
6184     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6185     * should make a best effort to make the newly focused child fully visible to the user.
6186     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6187     * other properties affecting visibility to the user as part of the focus change.</p>
6188     *
6189     * @return true if this view would prefer to become fully visible when it gains focus,
6190     *         false if it would prefer not to disrupt scroll positioning
6191     *
6192     * @see #setRevealOnFocusHint(boolean)
6193     */
6194    public final boolean getRevealOnFocusHint() {
6195        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6196    }
6197
6198    /**
6199     * Populates <code>outRect</code> with the hotspot bounds. By default,
6200     * the hotspot bounds are identical to the screen bounds.
6201     *
6202     * @param outRect rect to populate with hotspot bounds
6203     * @hide Only for internal use by views and widgets.
6204     */
6205    public void getHotspotBounds(Rect outRect) {
6206        final Drawable background = getBackground();
6207        if (background != null) {
6208            background.getHotspotBounds(outRect);
6209        } else {
6210            getBoundsOnScreen(outRect);
6211        }
6212    }
6213
6214    /**
6215     * Request that a rectangle of this view be visible on the screen,
6216     * scrolling if necessary just enough.
6217     *
6218     * <p>A View should call this if it maintains some notion of which part
6219     * of its content is interesting.  For example, a text editing view
6220     * should call this when its cursor moves.
6221     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6222     * It should not be affected by which part of the View is currently visible or its scroll
6223     * position.
6224     *
6225     * @param rectangle The rectangle in the View's content coordinate space
6226     * @return Whether any parent scrolled.
6227     */
6228    public boolean requestRectangleOnScreen(Rect rectangle) {
6229        return requestRectangleOnScreen(rectangle, false);
6230    }
6231
6232    /**
6233     * Request that a rectangle of this view be visible on the screen,
6234     * scrolling if necessary just enough.
6235     *
6236     * <p>A View should call this if it maintains some notion of which part
6237     * of its content is interesting.  For example, a text editing view
6238     * should call this when its cursor moves.
6239     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6240     * It should not be affected by which part of the View is currently visible or its scroll
6241     * position.
6242     * <p>When <code>immediate</code> is set to true, scrolling will not be
6243     * animated.
6244     *
6245     * @param rectangle The rectangle in the View's content coordinate space
6246     * @param immediate True to forbid animated scrolling, false otherwise
6247     * @return Whether any parent scrolled.
6248     */
6249    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6250        if (mParent == null) {
6251            return false;
6252        }
6253
6254        View child = this;
6255
6256        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6257        position.set(rectangle);
6258
6259        ViewParent parent = mParent;
6260        boolean scrolled = false;
6261        while (parent != null) {
6262            rectangle.set((int) position.left, (int) position.top,
6263                    (int) position.right, (int) position.bottom);
6264
6265            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6266
6267            if (!(parent instanceof View)) {
6268                break;
6269            }
6270
6271            // move it from child's content coordinate space to parent's content coordinate space
6272            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6273
6274            child = (View) parent;
6275            parent = child.getParent();
6276        }
6277
6278        return scrolled;
6279    }
6280
6281    /**
6282     * Called when this view wants to give up focus. If focus is cleared
6283     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6284     * <p>
6285     * <strong>Note:</strong> When a View clears focus the framework is trying
6286     * to give focus to the first focusable View from the top. Hence, if this
6287     * View is the first from the top that can take focus, then all callbacks
6288     * related to clearing focus will be invoked after which the framework will
6289     * give focus to this view.
6290     * </p>
6291     */
6292    public void clearFocus() {
6293        if (DBG) {
6294            System.out.println(this + " clearFocus()");
6295        }
6296
6297        clearFocusInternal(null, true, true);
6298    }
6299
6300    /**
6301     * Clears focus from the view, optionally propagating the change up through
6302     * the parent hierarchy and requesting that the root view place new focus.
6303     *
6304     * @param propagate whether to propagate the change up through the parent
6305     *            hierarchy
6306     * @param refocus when propagate is true, specifies whether to request the
6307     *            root view place new focus
6308     */
6309    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6310        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6311            mPrivateFlags &= ~PFLAG_FOCUSED;
6312
6313            if (propagate && mParent != null) {
6314                mParent.clearChildFocus(this);
6315            }
6316
6317            onFocusChanged(false, 0, null);
6318            refreshDrawableState();
6319
6320            if (propagate && (!refocus || !rootViewRequestFocus())) {
6321                notifyGlobalFocusCleared(this);
6322            }
6323        }
6324    }
6325
6326    void notifyGlobalFocusCleared(View oldFocus) {
6327        if (oldFocus != null && mAttachInfo != null) {
6328            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6329        }
6330    }
6331
6332    boolean rootViewRequestFocus() {
6333        final View root = getRootView();
6334        return root != null && root.requestFocus();
6335    }
6336
6337    /**
6338     * Called internally by the view system when a new view is getting focus.
6339     * This is what clears the old focus.
6340     * <p>
6341     * <b>NOTE:</b> The parent view's focused child must be updated manually
6342     * after calling this method. Otherwise, the view hierarchy may be left in
6343     * an inconstent state.
6344     */
6345    void unFocus(View focused) {
6346        if (DBG) {
6347            System.out.println(this + " unFocus()");
6348        }
6349
6350        clearFocusInternal(focused, false, false);
6351    }
6352
6353    /**
6354     * Returns true if this view has focus itself, or is the ancestor of the
6355     * view that has focus.
6356     *
6357     * @return True if this view has or contains focus, false otherwise.
6358     */
6359    @ViewDebug.ExportedProperty(category = "focus")
6360    public boolean hasFocus() {
6361        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6362    }
6363
6364    /**
6365     * Returns true if this view is focusable or if it contains a reachable View
6366     * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6367     * is a view whose parents do not block descendants focus.
6368     * Only {@link #VISIBLE} views are considered focusable.
6369     *
6370     * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6371     * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6372     * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6373     * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6374     * {@code false} for views not explicitly marked as focusable.
6375     * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6376     * behavior.</p>
6377     *
6378     * @return {@code true} if the view is focusable or if the view contains a focusable
6379     *         view, {@code false} otherwise
6380     *
6381     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6382     * @see ViewGroup#getTouchscreenBlocksFocus()
6383     * @see #hasExplicitFocusable()
6384     */
6385    public boolean hasFocusable() {
6386        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6387    }
6388
6389    /**
6390     * Returns true if this view is focusable or if it contains a reachable View
6391     * for which {@link #hasExplicitFocusable()} returns {@code true}.
6392     * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6393     * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6394     * {@link #FOCUSABLE} are considered focusable.
6395     *
6396     * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6397     * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6398     * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6399     * to focusable will not.</p>
6400     *
6401     * @return {@code true} if the view is focusable or if the view contains a focusable
6402     *         view, {@code false} otherwise
6403     *
6404     * @see #hasFocusable()
6405     */
6406    public boolean hasExplicitFocusable() {
6407        return hasFocusable(false, true);
6408    }
6409
6410    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6411        if (!isFocusableInTouchMode()) {
6412            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6413                final ViewGroup g = (ViewGroup) p;
6414                if (g.shouldBlockFocusForTouchscreen()) {
6415                    return false;
6416                }
6417            }
6418        }
6419        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6420            return false;
6421        }
6422        return (allowAutoFocus
6423                ? getFocusable() != NOT_FOCUSABLE
6424                : getFocusable() == FOCUSABLE) && isFocusable();
6425    }
6426
6427    /**
6428     * Called by the view system when the focus state of this view changes.
6429     * When the focus change event is caused by directional navigation, direction
6430     * and previouslyFocusedRect provide insight into where the focus is coming from.
6431     * When overriding, be sure to call up through to the super class so that
6432     * the standard focus handling will occur.
6433     *
6434     * @param gainFocus True if the View has focus; false otherwise.
6435     * @param direction The direction focus has moved when requestFocus()
6436     *                  is called to give this view focus. Values are
6437     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6438     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6439     *                  It may not always apply, in which case use the default.
6440     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6441     *        system, of the previously focused view.  If applicable, this will be
6442     *        passed in as finer grained information about where the focus is coming
6443     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6444     */
6445    @CallSuper
6446    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6447            @Nullable Rect previouslyFocusedRect) {
6448        if (gainFocus) {
6449            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6450        } else {
6451            notifyViewAccessibilityStateChangedIfNeeded(
6452                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6453        }
6454
6455        InputMethodManager imm = InputMethodManager.peekInstance();
6456        if (!gainFocus) {
6457            if (isPressed()) {
6458                setPressed(false);
6459            }
6460            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6461                imm.focusOut(this);
6462            }
6463            onFocusLost();
6464        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6465            imm.focusIn(this);
6466        }
6467
6468        if (isAutoFillable()) {
6469            AutoFillManager afm = getAutoFillManager();
6470            if (afm != null) {
6471                afm.focusChanged(this, gainFocus);
6472            }
6473        }
6474
6475        invalidate(true);
6476        ListenerInfo li = mListenerInfo;
6477        if (li != null && li.mOnFocusChangeListener != null) {
6478            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6479        }
6480
6481        if (mAttachInfo != null) {
6482            mAttachInfo.mKeyDispatchState.reset(this);
6483        }
6484    }
6485
6486    /**
6487     * Sends an accessibility event of the given type. If accessibility is
6488     * not enabled this method has no effect. The default implementation calls
6489     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6490     * to populate information about the event source (this View), then calls
6491     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6492     * populate the text content of the event source including its descendants,
6493     * and last calls
6494     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6495     * on its parent to request sending of the event to interested parties.
6496     * <p>
6497     * If an {@link AccessibilityDelegate} has been specified via calling
6498     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6499     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6500     * responsible for handling this call.
6501     * </p>
6502     *
6503     * @param eventType The type of the event to send, as defined by several types from
6504     * {@link android.view.accessibility.AccessibilityEvent}, such as
6505     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6506     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6507     *
6508     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6509     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6510     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6511     * @see AccessibilityDelegate
6512     */
6513    public void sendAccessibilityEvent(int eventType) {
6514        if (mAccessibilityDelegate != null) {
6515            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6516        } else {
6517            sendAccessibilityEventInternal(eventType);
6518        }
6519    }
6520
6521    /**
6522     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6523     * {@link AccessibilityEvent} to make an announcement which is related to some
6524     * sort of a context change for which none of the events representing UI transitions
6525     * is a good fit. For example, announcing a new page in a book. If accessibility
6526     * is not enabled this method does nothing.
6527     *
6528     * @param text The announcement text.
6529     */
6530    public void announceForAccessibility(CharSequence text) {
6531        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6532            AccessibilityEvent event = AccessibilityEvent.obtain(
6533                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6534            onInitializeAccessibilityEvent(event);
6535            event.getText().add(text);
6536            event.setContentDescription(null);
6537            mParent.requestSendAccessibilityEvent(this, event);
6538        }
6539    }
6540
6541    /**
6542     * @see #sendAccessibilityEvent(int)
6543     *
6544     * Note: Called from the default {@link AccessibilityDelegate}.
6545     *
6546     * @hide
6547     */
6548    public void sendAccessibilityEventInternal(int eventType) {
6549        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6550            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6551        }
6552    }
6553
6554    /**
6555     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6556     * takes as an argument an empty {@link AccessibilityEvent} and does not
6557     * perform a check whether accessibility is enabled.
6558     * <p>
6559     * If an {@link AccessibilityDelegate} has been specified via calling
6560     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6561     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6562     * is responsible for handling this call.
6563     * </p>
6564     *
6565     * @param event The event to send.
6566     *
6567     * @see #sendAccessibilityEvent(int)
6568     */
6569    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6570        if (mAccessibilityDelegate != null) {
6571            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6572        } else {
6573            sendAccessibilityEventUncheckedInternal(event);
6574        }
6575    }
6576
6577    /**
6578     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6579     *
6580     * Note: Called from the default {@link AccessibilityDelegate}.
6581     *
6582     * @hide
6583     */
6584    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6585        if (!isShown()) {
6586            return;
6587        }
6588        onInitializeAccessibilityEvent(event);
6589        // Only a subset of accessibility events populates text content.
6590        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6591            dispatchPopulateAccessibilityEvent(event);
6592        }
6593        // In the beginning we called #isShown(), so we know that getParent() is not null.
6594        getParent().requestSendAccessibilityEvent(this, event);
6595    }
6596
6597    /**
6598     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6599     * to its children for adding their text content to the event. Note that the
6600     * event text is populated in a separate dispatch path since we add to the
6601     * event not only the text of the source but also the text of all its descendants.
6602     * A typical implementation will call
6603     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6604     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6605     * on each child. Override this method if custom population of the event text
6606     * content is required.
6607     * <p>
6608     * If an {@link AccessibilityDelegate} has been specified via calling
6609     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6610     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6611     * is responsible for handling this call.
6612     * </p>
6613     * <p>
6614     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6615     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6616     * </p>
6617     *
6618     * @param event The event.
6619     *
6620     * @return True if the event population was completed.
6621     */
6622    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6623        if (mAccessibilityDelegate != null) {
6624            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6625        } else {
6626            return dispatchPopulateAccessibilityEventInternal(event);
6627        }
6628    }
6629
6630    /**
6631     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6632     *
6633     * Note: Called from the default {@link AccessibilityDelegate}.
6634     *
6635     * @hide
6636     */
6637    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6638        onPopulateAccessibilityEvent(event);
6639        return false;
6640    }
6641
6642    /**
6643     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6644     * giving a chance to this View to populate the accessibility event with its
6645     * text content. While this method is free to modify event
6646     * attributes other than text content, doing so should normally be performed in
6647     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6648     * <p>
6649     * Example: Adding formatted date string to an accessibility event in addition
6650     *          to the text added by the super implementation:
6651     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6652     *     super.onPopulateAccessibilityEvent(event);
6653     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6654     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6655     *         mCurrentDate.getTimeInMillis(), flags);
6656     *     event.getText().add(selectedDateUtterance);
6657     * }</pre>
6658     * <p>
6659     * If an {@link AccessibilityDelegate} has been specified via calling
6660     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6661     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6662     * is responsible for handling this call.
6663     * </p>
6664     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6665     * information to the event, in case the default implementation has basic information to add.
6666     * </p>
6667     *
6668     * @param event The accessibility event which to populate.
6669     *
6670     * @see #sendAccessibilityEvent(int)
6671     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6672     */
6673    @CallSuper
6674    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6675        if (mAccessibilityDelegate != null) {
6676            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6677        } else {
6678            onPopulateAccessibilityEventInternal(event);
6679        }
6680    }
6681
6682    /**
6683     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6684     *
6685     * Note: Called from the default {@link AccessibilityDelegate}.
6686     *
6687     * @hide
6688     */
6689    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6690    }
6691
6692    /**
6693     * Initializes an {@link AccessibilityEvent} with information about
6694     * this View which is the event source. In other words, the source of
6695     * an accessibility event is the view whose state change triggered firing
6696     * the event.
6697     * <p>
6698     * Example: Setting the password property of an event in addition
6699     *          to properties set by the super implementation:
6700     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6701     *     super.onInitializeAccessibilityEvent(event);
6702     *     event.setPassword(true);
6703     * }</pre>
6704     * <p>
6705     * If an {@link AccessibilityDelegate} has been specified via calling
6706     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6707     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6708     * is responsible for handling this call.
6709     * </p>
6710     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6711     * information to the event, in case the default implementation has basic information to add.
6712     * </p>
6713     * @param event The event to initialize.
6714     *
6715     * @see #sendAccessibilityEvent(int)
6716     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6717     */
6718    @CallSuper
6719    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6720        if (mAccessibilityDelegate != null) {
6721            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6722        } else {
6723            onInitializeAccessibilityEventInternal(event);
6724        }
6725    }
6726
6727    /**
6728     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6729     *
6730     * Note: Called from the default {@link AccessibilityDelegate}.
6731     *
6732     * @hide
6733     */
6734    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6735        event.setSource(this);
6736        event.setClassName(getAccessibilityClassName());
6737        event.setPackageName(getContext().getPackageName());
6738        event.setEnabled(isEnabled());
6739        event.setContentDescription(mContentDescription);
6740
6741        switch (event.getEventType()) {
6742            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6743                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6744                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6745                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6746                event.setItemCount(focusablesTempList.size());
6747                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6748                if (mAttachInfo != null) {
6749                    focusablesTempList.clear();
6750                }
6751            } break;
6752            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6753                CharSequence text = getIterableTextForAccessibility();
6754                if (text != null && text.length() > 0) {
6755                    event.setFromIndex(getAccessibilitySelectionStart());
6756                    event.setToIndex(getAccessibilitySelectionEnd());
6757                    event.setItemCount(text.length());
6758                }
6759            } break;
6760        }
6761    }
6762
6763    /**
6764     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6765     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6766     * This method is responsible for obtaining an accessibility node info from a
6767     * pool of reusable instances and calling
6768     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6769     * initialize the former.
6770     * <p>
6771     * Note: The client is responsible for recycling the obtained instance by calling
6772     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6773     * </p>
6774     *
6775     * @return A populated {@link AccessibilityNodeInfo}.
6776     *
6777     * @see AccessibilityNodeInfo
6778     */
6779    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6780        if (mAccessibilityDelegate != null) {
6781            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6782        } else {
6783            return createAccessibilityNodeInfoInternal();
6784        }
6785    }
6786
6787    /**
6788     * @see #createAccessibilityNodeInfo()
6789     *
6790     * @hide
6791     */
6792    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6793        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6794        if (provider != null) {
6795            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6796        } else {
6797            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6798            onInitializeAccessibilityNodeInfo(info);
6799            return info;
6800        }
6801    }
6802
6803    /**
6804     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6805     * The base implementation sets:
6806     * <ul>
6807     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6808     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6809     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6810     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6811     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6812     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6813     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6814     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6815     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6816     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6817     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6818     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6819     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6820     * </ul>
6821     * <p>
6822     * Subclasses should override this method, call the super implementation,
6823     * and set additional attributes.
6824     * </p>
6825     * <p>
6826     * If an {@link AccessibilityDelegate} has been specified via calling
6827     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6828     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6829     * is responsible for handling this call.
6830     * </p>
6831     *
6832     * @param info The instance to initialize.
6833     */
6834    @CallSuper
6835    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6836        if (mAccessibilityDelegate != null) {
6837            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6838        } else {
6839            onInitializeAccessibilityNodeInfoInternal(info);
6840        }
6841    }
6842
6843    /**
6844     * Gets the location of this view in screen coordinates.
6845     *
6846     * @param outRect The output location
6847     * @hide
6848     */
6849    public void getBoundsOnScreen(Rect outRect) {
6850        getBoundsOnScreen(outRect, false);
6851    }
6852
6853    /**
6854     * Gets the location of this view in screen coordinates.
6855     *
6856     * @param outRect The output location
6857     * @param clipToParent Whether to clip child bounds to the parent ones.
6858     * @hide
6859     */
6860    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6861        if (mAttachInfo == null) {
6862            return;
6863        }
6864
6865        RectF position = mAttachInfo.mTmpTransformRect;
6866        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6867
6868        if (!hasIdentityMatrix()) {
6869            getMatrix().mapRect(position);
6870        }
6871
6872        position.offset(mLeft, mTop);
6873
6874        ViewParent parent = mParent;
6875        while (parent instanceof View) {
6876            View parentView = (View) parent;
6877
6878            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6879
6880            if (clipToParent) {
6881                position.left = Math.max(position.left, 0);
6882                position.top = Math.max(position.top, 0);
6883                position.right = Math.min(position.right, parentView.getWidth());
6884                position.bottom = Math.min(position.bottom, parentView.getHeight());
6885            }
6886
6887            if (!parentView.hasIdentityMatrix()) {
6888                parentView.getMatrix().mapRect(position);
6889            }
6890
6891            position.offset(parentView.mLeft, parentView.mTop);
6892
6893            parent = parentView.mParent;
6894        }
6895
6896        if (parent instanceof ViewRootImpl) {
6897            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6898            position.offset(0, -viewRootImpl.mCurScrollY);
6899        }
6900
6901        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6902
6903        outRect.set(Math.round(position.left), Math.round(position.top),
6904                Math.round(position.right), Math.round(position.bottom));
6905    }
6906
6907    /**
6908     * Return the class name of this object to be used for accessibility purposes.
6909     * Subclasses should only override this if they are implementing something that
6910     * should be seen as a completely new class of view when used by accessibility,
6911     * unrelated to the class it is deriving from.  This is used to fill in
6912     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6913     */
6914    public CharSequence getAccessibilityClassName() {
6915        return View.class.getName();
6916    }
6917
6918    /**
6919     * Called when assist structure is being retrieved from a view as part of
6920     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6921     * @param structure Fill in with structured view data.  The default implementation
6922     * fills in all data that can be inferred from the view itself.
6923     */
6924    public void onProvideStructure(ViewStructure structure) {
6925        onProvideStructureForAssistOrAutoFill(structure, false);
6926    }
6927
6928    /**
6929     * Called when assist structure is being retrieved from a view as part of an auto-fill request.
6930     *
6931     * <p>When implementing this method, subclasses must also:
6932     *
6933     * <ol>
6934     * <li>Implement {@link #autoFill(AutoFillValue)}, {@link #getAutoFillType()}
6935     * and {@link #getAutoFillValue()}.
6936     * <li>Call {@link android.view.autofill.AutoFillManager#virtualValueChanged(View, int,
6937     * AutoFillValue)} when its value changed.
6938     * </ol>
6939     *
6940     * @param structure Fill in with structured view data. The default implementation
6941     * fills in all data that can be inferred from the view itself.
6942     * @param flags optional flags (currently {@code 0}).
6943     */
6944    public void onProvideAutoFillStructure(ViewStructure structure, int flags) {
6945        onProvideStructureForAssistOrAutoFill(structure, true);
6946    }
6947
6948    private void onProvideStructureForAssistOrAutoFill(ViewStructure structure,
6949            boolean forAutoFill) {
6950        final int id = mID;
6951        if (id != NO_ID && !isViewIdGenerated(id)) {
6952            String pkg, type, entry;
6953            try {
6954                final Resources res = getResources();
6955                entry = res.getResourceEntryName(id);
6956                type = res.getResourceTypeName(id);
6957                pkg = res.getResourcePackageName(id);
6958            } catch (Resources.NotFoundException e) {
6959                entry = type = pkg = null;
6960            }
6961            structure.setId(id, pkg, type, entry);
6962        } else {
6963            structure.setId(id, null, null, null);
6964        }
6965
6966        if (forAutoFill) {
6967            final AutoFillType autoFillType = getAutoFillType();
6968            // Don't need to fill auto-fill info if view does not support it.
6969            // For example, only TextViews that are editable support auto-fill
6970            if (autoFillType != null) {
6971                // The auto-fill id needs to be unique, but its value doesn't matter, so it's better
6972                // to reuse the accessibility id to save space.
6973                structure.setAutoFillId(getAccessibilityViewId());
6974                structure.setAutoFillType(autoFillType);
6975                structure.setAutoFillValue(getAutoFillValue());
6976            }
6977        }
6978
6979        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6980        if (!hasIdentityMatrix()) {
6981            structure.setTransformation(getMatrix());
6982        }
6983        structure.setElevation(getZ());
6984        structure.setVisibility(getVisibility());
6985        structure.setEnabled(isEnabled());
6986        if (isClickable()) {
6987            structure.setClickable(true);
6988        }
6989        if (isFocusable()) {
6990            structure.setFocusable(true);
6991        }
6992        if (isFocused()) {
6993            structure.setFocused(true);
6994        }
6995        if (isAccessibilityFocused()) {
6996            structure.setAccessibilityFocused(true);
6997        }
6998        if (isSelected()) {
6999            structure.setSelected(true);
7000        }
7001        if (isActivated()) {
7002            structure.setActivated(true);
7003        }
7004        if (isLongClickable()) {
7005            structure.setLongClickable(true);
7006        }
7007        if (this instanceof Checkable) {
7008            structure.setCheckable(true);
7009            if (((Checkable)this).isChecked()) {
7010                structure.setChecked(true);
7011            }
7012        }
7013        if (isContextClickable()) {
7014            structure.setContextClickable(true);
7015        }
7016        structure.setClassName(getAccessibilityClassName().toString());
7017        structure.setContentDescription(getContentDescription());
7018    }
7019
7020    /**
7021     * Called when assist structure is being retrieved from a view as part of
7022     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7023     * generate additional virtual structure under this view.  The defaullt implementation
7024     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7025     * view's virtual accessibility nodes, if any.  You can override this for a more
7026     * optimal implementation providing this data.
7027     */
7028    public void onProvideVirtualStructure(ViewStructure structure) {
7029        onProvideVirtualStructureForAssistOrAutoFill(structure, false);
7030    }
7031
7032    /**
7033     * Called when assist structure is being retrieved from a view as part of an auto-fill request
7034     * to generate additional virtual structure under this view.
7035     *
7036     * <p>The default implementation uses {@link #getAccessibilityNodeProvider()} to try to
7037     * generate this from the view's virtual accessibility nodes, if any. You can override this
7038     * for a more optimal implementation providing this data.
7039     *
7040     * <p>When implementing this method, subclasses must follow the rules below:
7041     *
7042     * <ol>
7043     * <li>Also implement {@link #autoFillVirtual(int, AutoFillValue)} to auto-fill the virtual
7044     * children.
7045     * <li>Call {@link android.view.autofill.AutoFillManager#virtualFocusChanged(View, int, Rect,
7046     * boolean)} when the focus inside the view changed.
7047     * <li>Call {@link android.view.autofill.AutoFillManager#virtualValueChanged(View, int,
7048     * AutoFillValue)} when the value of a child changed.
7049     * <li>Call {@link android.view.autofill.AutoFillManager#reset()} when the auto-fill context
7050     * of the view structure changed.
7051     * </ol>
7052     *
7053     * @param structure Fill in with structured view data.
7054     * @param flags optional flags (currently {@code 0}).
7055     */
7056    public void onProvideAutoFillVirtualStructure(ViewStructure structure, int flags) {
7057        onProvideVirtualStructureForAssistOrAutoFill(structure, true);
7058    }
7059
7060    private void onProvideVirtualStructureForAssistOrAutoFill(ViewStructure structure,
7061            boolean forAutoFill) {
7062        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
7063        // this method should take a boolean with the type of request.
7064        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7065        if (provider != null) {
7066            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7067            structure.setChildCount(1);
7068            ViewStructure root = structure.newChild(0);
7069            populateVirtualStructure(root, provider, info, forAutoFill);
7070            info.recycle();
7071        }
7072    }
7073
7074    /**
7075     * Automatically fills the content of this view with the {@code value}.
7076     *
7077     * <p>By default does nothing, but views should override it (and {@link #getAutoFillType()},
7078     * {@link #getAutoFillValue()}, and {@link #onProvideAutoFillStructure(ViewStructure, int)}
7079     * to support the AutoFill Framework.
7080     *
7081     * <p>Typically, it is implemented by:
7082     *
7083     * <ol>
7084     * <li>Calling the proper getter method on {@link AutoFillValue} to fetch the actual value.
7085     * <li>Passing the actual value to the equivalent setter in the view.
7086     * <ol>
7087     *
7088     * <p>For example, a text-field view would call:
7089     *
7090     * <pre class="prettyprint">
7091     * CharSequence text = value.getTextValue();
7092     * if (text != null) {
7093     *     setText(text);
7094     * }
7095     * </pre>
7096     *
7097     * @param value value to be auto-filled.
7098     */
7099    public void autoFill(@SuppressWarnings("unused") AutoFillValue value) {
7100    }
7101
7102    /**
7103     * Automatically fills the content of a virtual view with the {@code value}
7104     *
7105     * <p>See {@link #autoFill(AutoFillValue)} and
7106     * {@link #onProvideAutoFillVirtualStructure(ViewStructure, int)} for more info.
7107     *
7108     * @param value value to be auto-filled.
7109     * @param virtualId id identifying the virtual child inside the custom view.
7110     */
7111    public void autoFillVirtual(@SuppressWarnings("unused") int virtualId,
7112            @SuppressWarnings("unused") AutoFillValue value) {
7113    }
7114
7115    /**
7116     * Describes the auto-fill type that should be used on calls to
7117     * {@link #autoFill(AutoFillValue)} and {@link #autoFillVirtual(int, AutoFillValue)}.
7118
7119     * <p>By default returns {@code null}, but views should override it (and
7120     * {@link #autoFill(AutoFillValue)} to support the AutoFill Framework.
7121     */
7122    @Nullable
7123    public AutoFillType getAutoFillType() {
7124        return null;
7125    }
7126
7127    /**
7128     * Gets the {@link View}'s current auto-fill value.
7129     *
7130     * <p>By default returns {@code null}, but views should override it,
7131     * {@link #autoFill(AutoFillValue)}, and {@link #getAutoFillType()} to support the AutoFill
7132     * Framework.
7133     */
7134    @Nullable
7135    public AutoFillValue getAutoFillValue() {
7136        return null;
7137    }
7138
7139    @Nullable
7140    private AutoFillManager getAutoFillManager() {
7141        return mContext.getSystemService(AutoFillManager.class);
7142    }
7143
7144    private boolean isAutoFillable() {
7145        return getAutoFillType() != null && !isAutoFillBlocked();
7146    }
7147
7148    private void populateVirtualStructure(ViewStructure structure,
7149            AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutoFill) {
7150        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7151                null, null, null);
7152        Rect rect = structure.getTempRect();
7153        info.getBoundsInParent(rect);
7154        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7155        structure.setVisibility(VISIBLE);
7156        structure.setEnabled(info.isEnabled());
7157        if (info.isClickable()) {
7158            structure.setClickable(true);
7159        }
7160        if (info.isFocusable()) {
7161            structure.setFocusable(true);
7162        }
7163        if (info.isFocused()) {
7164            structure.setFocused(true);
7165        }
7166        if (info.isAccessibilityFocused()) {
7167            structure.setAccessibilityFocused(true);
7168        }
7169        if (info.isSelected()) {
7170            structure.setSelected(true);
7171        }
7172        if (info.isLongClickable()) {
7173            structure.setLongClickable(true);
7174        }
7175        if (info.isCheckable()) {
7176            structure.setCheckable(true);
7177            if (info.isChecked()) {
7178                structure.setChecked(true);
7179            }
7180        }
7181        if (info.isContextClickable()) {
7182            structure.setContextClickable(true);
7183        }
7184        CharSequence cname = info.getClassName();
7185        structure.setClassName(cname != null ? cname.toString() : null);
7186        structure.setContentDescription(info.getContentDescription());
7187        if (!forAutoFill && (info.getText() != null || info.getError() != null)) {
7188            // TODO(b/33197203) (b/33269702): when sanitized, try to use the Accessibility API to
7189            // just set sanitized values (like text coming from resource files), rather than not
7190            // setting it at all.
7191            structure.setText(info.getText(), info.getTextSelectionStart(),
7192                    info.getTextSelectionEnd());
7193        }
7194        final int NCHILDREN = info.getChildCount();
7195        if (NCHILDREN > 0) {
7196            structure.setChildCount(NCHILDREN);
7197            for (int i=0; i<NCHILDREN; i++) {
7198                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7199                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7200                ViewStructure child = structure.newChild(i);
7201                populateVirtualStructure(child, provider, cinfo, forAutoFill);
7202                cinfo.recycle();
7203            }
7204        }
7205    }
7206
7207    /**
7208     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7209     * implementation calls {@link #onProvideStructure} and
7210     * {@link #onProvideVirtualStructure}.
7211     */
7212    public void dispatchProvideStructure(ViewStructure structure) {
7213        dispatchProvideStructureForAssistOrAutoFill(structure, false);
7214    }
7215
7216    /**
7217     * Dispatch creation of {@link ViewStructure} down the hierarchy.
7218     *
7219     * <p>The structure must be filled according to the request type, which is set in the
7220     * {@code flags} parameter - see the documentation on each flag for more details.
7221     *
7222     * <p>The default implementation calls {@link #onProvideAutoFillStructure(ViewStructure, int)}
7223     * and {@link #onProvideAutoFillVirtualStructure(ViewStructure, int)}.
7224     *
7225     * @param structure Fill in with structured view data.
7226     * @param flags optional flags (currently {@code 0}).
7227     */
7228    public void dispatchProvideAutoFillStructure(ViewStructure structure, int flags) {
7229        dispatchProvideStructureForAssistOrAutoFill(structure, true);
7230    }
7231
7232    private void dispatchProvideStructureForAssistOrAutoFill(ViewStructure structure,
7233            boolean forAutoFill) {
7234        boolean blocked = forAutoFill ? isAutoFillBlocked() : isAssistBlocked();
7235        if (!blocked) {
7236            if (forAutoFill) {
7237                // The auto-fill id needs to be unique, but its value doesn't matter,
7238                // so it's better to reuse the accessibility id to save space.
7239                structure.setAutoFillId(getAccessibilityViewId());
7240                // NOTE: flags are not currently supported, hence 0
7241                onProvideAutoFillStructure(structure, 0);
7242                onProvideAutoFillVirtualStructure(structure, 0);
7243            } else {
7244                onProvideStructure(structure);
7245                onProvideVirtualStructure(structure);
7246            }
7247        } else {
7248            structure.setClassName(getAccessibilityClassName().toString());
7249            structure.setAssistBlocked(true);
7250        }
7251    }
7252
7253    /**
7254     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7255     *
7256     * Note: Called from the default {@link AccessibilityDelegate}.
7257     *
7258     * @hide
7259     */
7260    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7261        if (mAttachInfo == null) {
7262            return;
7263        }
7264
7265        Rect bounds = mAttachInfo.mTmpInvalRect;
7266
7267        getDrawingRect(bounds);
7268        info.setBoundsInParent(bounds);
7269
7270        getBoundsOnScreen(bounds, true);
7271        info.setBoundsInScreen(bounds);
7272
7273        ViewParent parent = getParentForAccessibility();
7274        if (parent instanceof View) {
7275            info.setParent((View) parent);
7276        }
7277
7278        if (mID != View.NO_ID) {
7279            View rootView = getRootView();
7280            if (rootView == null) {
7281                rootView = this;
7282            }
7283
7284            View label = rootView.findLabelForView(this, mID);
7285            if (label != null) {
7286                info.setLabeledBy(label);
7287            }
7288
7289            if ((mAttachInfo.mAccessibilityFetchFlags
7290                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7291                    && Resources.resourceHasPackage(mID)) {
7292                try {
7293                    String viewId = getResources().getResourceName(mID);
7294                    info.setViewIdResourceName(viewId);
7295                } catch (Resources.NotFoundException nfe) {
7296                    /* ignore */
7297                }
7298            }
7299        }
7300
7301        if (mLabelForId != View.NO_ID) {
7302            View rootView = getRootView();
7303            if (rootView == null) {
7304                rootView = this;
7305            }
7306            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7307            if (labeled != null) {
7308                info.setLabelFor(labeled);
7309            }
7310        }
7311
7312        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7313            View rootView = getRootView();
7314            if (rootView == null) {
7315                rootView = this;
7316            }
7317            View next = rootView.findViewInsideOutShouldExist(this,
7318                    mAccessibilityTraversalBeforeId);
7319            if (next != null && next.includeForAccessibility()) {
7320                info.setTraversalBefore(next);
7321            }
7322        }
7323
7324        if (mAccessibilityTraversalAfterId != View.NO_ID) {
7325            View rootView = getRootView();
7326            if (rootView == null) {
7327                rootView = this;
7328            }
7329            View next = rootView.findViewInsideOutShouldExist(this,
7330                    mAccessibilityTraversalAfterId);
7331            if (next != null && next.includeForAccessibility()) {
7332                info.setTraversalAfter(next);
7333            }
7334        }
7335
7336        info.setVisibleToUser(isVisibleToUser());
7337
7338        info.setImportantForAccessibility(isImportantForAccessibility());
7339        info.setPackageName(mContext.getPackageName());
7340        info.setClassName(getAccessibilityClassName());
7341        info.setContentDescription(getContentDescription());
7342
7343        info.setEnabled(isEnabled());
7344        info.setClickable(isClickable());
7345        info.setFocusable(isFocusable());
7346        info.setFocused(isFocused());
7347        info.setAccessibilityFocused(isAccessibilityFocused());
7348        info.setSelected(isSelected());
7349        info.setLongClickable(isLongClickable());
7350        info.setContextClickable(isContextClickable());
7351        info.setLiveRegion(getAccessibilityLiveRegion());
7352
7353        // TODO: These make sense only if we are in an AdapterView but all
7354        // views can be selected. Maybe from accessibility perspective
7355        // we should report as selectable view in an AdapterView.
7356        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
7357        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
7358
7359        if (isFocusable()) {
7360            if (isFocused()) {
7361                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
7362            } else {
7363                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
7364            }
7365        }
7366
7367        if (!isAccessibilityFocused()) {
7368            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
7369        } else {
7370            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
7371        }
7372
7373        if (isClickable() && isEnabled()) {
7374            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
7375        }
7376
7377        if (isLongClickable() && isEnabled()) {
7378            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
7379        }
7380
7381        if (isContextClickable() && isEnabled()) {
7382            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
7383        }
7384
7385        CharSequence text = getIterableTextForAccessibility();
7386        if (text != null && text.length() > 0) {
7387            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
7388
7389            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
7390            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7391            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7392            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7393                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7394                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7395        }
7396
7397        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7398        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7399    }
7400
7401    /**
7402     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
7403     * additional data.
7404     * <p>
7405     * This method only needs overloading if the node is marked as having extra data available.
7406     * </p>
7407     *
7408     * @param info The info to which to add the extra data. Never {@code null}.
7409     * @param extraDataKey A key specifying the type of extra data to add to the info. The
7410     *                     extra data should be added to the {@link Bundle} returned by
7411     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
7412     *                     {@code null}.
7413     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
7414     *                  {@code null} if the service provided no arguments.
7415     *
7416     * @see AccessibilityNodeInfo#setExtraAvailableData
7417     */
7418    public void addExtraDataToAccessibilityNodeInfo(
7419            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
7420            @Nullable Bundle arguments) {
7421    }
7422
7423    /**
7424     * Determine the order in which this view will be drawn relative to its siblings for a11y
7425     *
7426     * @param info The info whose drawing order should be populated
7427     */
7428    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7429        /*
7430         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7431         * drawing order may not be well-defined, and some Views with custom drawing order may
7432         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7433         */
7434        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7435            info.setDrawingOrder(0);
7436            return;
7437        }
7438        int drawingOrderInParent = 1;
7439        // Iterate up the hierarchy if parents are not important for a11y
7440        View viewAtDrawingLevel = this;
7441        final ViewParent parent = getParentForAccessibility();
7442        while (viewAtDrawingLevel != parent) {
7443            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7444            if (!(currentParent instanceof ViewGroup)) {
7445                // Should only happen for the Decor
7446                drawingOrderInParent = 0;
7447                break;
7448            } else {
7449                final ViewGroup parentGroup = (ViewGroup) currentParent;
7450                final int childCount = parentGroup.getChildCount();
7451                if (childCount > 1) {
7452                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7453                    if (preorderedList != null) {
7454                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7455                        for (int i = 0; i < childDrawIndex; i++) {
7456                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7457                        }
7458                    } else {
7459                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7460                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7461                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7462                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7463                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7464                        if (childDrawIndex != 0) {
7465                            for (int i = 0; i < numChildrenToIterate; i++) {
7466                                final int otherDrawIndex = (customOrder ?
7467                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7468                                if (otherDrawIndex < childDrawIndex) {
7469                                    drawingOrderInParent +=
7470                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7471                                }
7472                            }
7473                        }
7474                    }
7475                }
7476            }
7477            viewAtDrawingLevel = (View) currentParent;
7478        }
7479        info.setDrawingOrder(drawingOrderInParent);
7480    }
7481
7482    private static int numViewsForAccessibility(View view) {
7483        if (view != null) {
7484            if (view.includeForAccessibility()) {
7485                return 1;
7486            } else if (view instanceof ViewGroup) {
7487                return ((ViewGroup) view).getNumChildrenForAccessibility();
7488            }
7489        }
7490        return 0;
7491    }
7492
7493    private View findLabelForView(View view, int labeledId) {
7494        if (mMatchLabelForPredicate == null) {
7495            mMatchLabelForPredicate = new MatchLabelForPredicate();
7496        }
7497        mMatchLabelForPredicate.mLabeledId = labeledId;
7498        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
7499    }
7500
7501    /**
7502     * Computes whether this view is visible to the user. Such a view is
7503     * attached, visible, all its predecessors are visible, it is not clipped
7504     * entirely by its predecessors, and has an alpha greater than zero.
7505     *
7506     * @return Whether the view is visible on the screen.
7507     *
7508     * @hide
7509     */
7510    protected boolean isVisibleToUser() {
7511        return isVisibleToUser(null);
7512    }
7513
7514    /**
7515     * Computes whether the given portion of this view is visible to the user.
7516     * Such a view is attached, visible, all its predecessors are visible,
7517     * has an alpha greater than zero, and the specified portion is not
7518     * clipped entirely by its predecessors.
7519     *
7520     * @param boundInView the portion of the view to test; coordinates should be relative; may be
7521     *                    <code>null</code>, and the entire view will be tested in this case.
7522     *                    When <code>true</code> is returned by the function, the actual visible
7523     *                    region will be stored in this parameter; that is, if boundInView is fully
7524     *                    contained within the view, no modification will be made, otherwise regions
7525     *                    outside of the visible area of the view will be clipped.
7526     *
7527     * @return Whether the specified portion of the view is visible on the screen.
7528     *
7529     * @hide
7530     */
7531    protected boolean isVisibleToUser(Rect boundInView) {
7532        if (mAttachInfo != null) {
7533            // Attached to invisible window means this view is not visible.
7534            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
7535                return false;
7536            }
7537            // An invisible predecessor or one with alpha zero means
7538            // that this view is not visible to the user.
7539            Object current = this;
7540            while (current instanceof View) {
7541                View view = (View) current;
7542                // We have attach info so this view is attached and there is no
7543                // need to check whether we reach to ViewRootImpl on the way up.
7544                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
7545                        view.getVisibility() != VISIBLE) {
7546                    return false;
7547                }
7548                current = view.mParent;
7549            }
7550            // Check if the view is entirely covered by its predecessors.
7551            Rect visibleRect = mAttachInfo.mTmpInvalRect;
7552            Point offset = mAttachInfo.mPoint;
7553            if (!getGlobalVisibleRect(visibleRect, offset)) {
7554                return false;
7555            }
7556            // Check if the visible portion intersects the rectangle of interest.
7557            if (boundInView != null) {
7558                visibleRect.offset(-offset.x, -offset.y);
7559                return boundInView.intersect(visibleRect);
7560            }
7561            return true;
7562        }
7563        return false;
7564    }
7565
7566    /**
7567     * Returns the delegate for implementing accessibility support via
7568     * composition. For more details see {@link AccessibilityDelegate}.
7569     *
7570     * @return The delegate, or null if none set.
7571     *
7572     * @hide
7573     */
7574    public AccessibilityDelegate getAccessibilityDelegate() {
7575        return mAccessibilityDelegate;
7576    }
7577
7578    /**
7579     * Sets a delegate for implementing accessibility support via composition
7580     * (as opposed to inheritance). For more details, see
7581     * {@link AccessibilityDelegate}.
7582     * <p>
7583     * <strong>Note:</strong> On platform versions prior to
7584     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
7585     * views in the {@code android.widget.*} package are called <i>before</i>
7586     * host methods. This prevents certain properties such as class name from
7587     * being modified by overriding
7588     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
7589     * as any changes will be overwritten by the host class.
7590     * <p>
7591     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
7592     * methods are called <i>after</i> host methods, which all properties to be
7593     * modified without being overwritten by the host class.
7594     *
7595     * @param delegate the object to which accessibility method calls should be
7596     *                 delegated
7597     * @see AccessibilityDelegate
7598     */
7599    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
7600        mAccessibilityDelegate = delegate;
7601    }
7602
7603    /**
7604     * Gets the provider for managing a virtual view hierarchy rooted at this View
7605     * and reported to {@link android.accessibilityservice.AccessibilityService}s
7606     * that explore the window content.
7607     * <p>
7608     * If this method returns an instance, this instance is responsible for managing
7609     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
7610     * View including the one representing the View itself. Similarly the returned
7611     * instance is responsible for performing accessibility actions on any virtual
7612     * view or the root view itself.
7613     * </p>
7614     * <p>
7615     * If an {@link AccessibilityDelegate} has been specified via calling
7616     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7617     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
7618     * is responsible for handling this call.
7619     * </p>
7620     *
7621     * @return The provider.
7622     *
7623     * @see AccessibilityNodeProvider
7624     */
7625    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
7626        if (mAccessibilityDelegate != null) {
7627            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
7628        } else {
7629            return null;
7630        }
7631    }
7632
7633    /**
7634     * Gets the unique identifier of this view on the screen for accessibility purposes.
7635     *
7636     * @return The view accessibility id.
7637     *
7638     * @hide
7639     */
7640    public int getAccessibilityViewId() {
7641        if (mAccessibilityViewId == NO_ID) {
7642            mAccessibilityViewId = sNextAccessibilityViewId++;
7643        }
7644        return mAccessibilityViewId;
7645    }
7646
7647    /**
7648     * Gets the unique identifier of the window in which this View reseides.
7649     *
7650     * @return The window accessibility id.
7651     *
7652     * @hide
7653     */
7654    public int getAccessibilityWindowId() {
7655        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
7656                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
7657    }
7658
7659    /**
7660     * Returns the {@link View}'s content description.
7661     * <p>
7662     * <strong>Note:</strong> Do not override this method, as it will have no
7663     * effect on the content description presented to accessibility services.
7664     * You must call {@link #setContentDescription(CharSequence)} to modify the
7665     * content description.
7666     *
7667     * @return the content description
7668     * @see #setContentDescription(CharSequence)
7669     * @attr ref android.R.styleable#View_contentDescription
7670     */
7671    @ViewDebug.ExportedProperty(category = "accessibility")
7672    public CharSequence getContentDescription() {
7673        return mContentDescription;
7674    }
7675
7676    /**
7677     * Sets the {@link View}'s content description.
7678     * <p>
7679     * A content description briefly describes the view and is primarily used
7680     * for accessibility support to determine how a view should be presented to
7681     * the user. In the case of a view with no textual representation, such as
7682     * {@link android.widget.ImageButton}, a useful content description
7683     * explains what the view does. For example, an image button with a phone
7684     * icon that is used to place a call may use "Call" as its content
7685     * description. An image of a floppy disk that is used to save a file may
7686     * use "Save".
7687     *
7688     * @param contentDescription The content description.
7689     * @see #getContentDescription()
7690     * @attr ref android.R.styleable#View_contentDescription
7691     */
7692    @RemotableViewMethod
7693    public void setContentDescription(CharSequence contentDescription) {
7694        if (mContentDescription == null) {
7695            if (contentDescription == null) {
7696                return;
7697            }
7698        } else if (mContentDescription.equals(contentDescription)) {
7699            return;
7700        }
7701        mContentDescription = contentDescription;
7702        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
7703        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
7704            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
7705            notifySubtreeAccessibilityStateChangedIfNeeded();
7706        } else {
7707            notifyViewAccessibilityStateChangedIfNeeded(
7708                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
7709        }
7710    }
7711
7712    /**
7713     * Sets the id of a view before which this one is visited in accessibility traversal.
7714     * A screen-reader must visit the content of this view before the content of the one
7715     * it precedes. For example, if view B is set to be before view A, then a screen-reader
7716     * will traverse the entire content of B before traversing the entire content of A,
7717     * regardles of what traversal strategy it is using.
7718     * <p>
7719     * Views that do not have specified before/after relationships are traversed in order
7720     * determined by the screen-reader.
7721     * </p>
7722     * <p>
7723     * Setting that this view is before a view that is not important for accessibility
7724     * or if this view is not important for accessibility will have no effect as the
7725     * screen-reader is not aware of unimportant views.
7726     * </p>
7727     *
7728     * @param beforeId The id of a view this one precedes in accessibility traversal.
7729     *
7730     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
7731     *
7732     * @see #setImportantForAccessibility(int)
7733     */
7734    @RemotableViewMethod
7735    public void setAccessibilityTraversalBefore(int beforeId) {
7736        if (mAccessibilityTraversalBeforeId == beforeId) {
7737            return;
7738        }
7739        mAccessibilityTraversalBeforeId = beforeId;
7740        notifyViewAccessibilityStateChangedIfNeeded(
7741                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7742    }
7743
7744    /**
7745     * Gets the id of a view before which this one is visited in accessibility traversal.
7746     *
7747     * @return The id of a view this one precedes in accessibility traversal if
7748     *         specified, otherwise {@link #NO_ID}.
7749     *
7750     * @see #setAccessibilityTraversalBefore(int)
7751     */
7752    public int getAccessibilityTraversalBefore() {
7753        return mAccessibilityTraversalBeforeId;
7754    }
7755
7756    /**
7757     * Sets the id of a view after which this one is visited in accessibility traversal.
7758     * A screen-reader must visit the content of the other view before the content of this
7759     * one. For example, if view B is set to be after view A, then a screen-reader
7760     * will traverse the entire content of A before traversing the entire content of B,
7761     * regardles of what traversal strategy it is using.
7762     * <p>
7763     * Views that do not have specified before/after relationships are traversed in order
7764     * determined by the screen-reader.
7765     * </p>
7766     * <p>
7767     * Setting that this view is after a view that is not important for accessibility
7768     * or if this view is not important for accessibility will have no effect as the
7769     * screen-reader is not aware of unimportant views.
7770     * </p>
7771     *
7772     * @param afterId The id of a view this one succedees in accessibility traversal.
7773     *
7774     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
7775     *
7776     * @see #setImportantForAccessibility(int)
7777     */
7778    @RemotableViewMethod
7779    public void setAccessibilityTraversalAfter(int afterId) {
7780        if (mAccessibilityTraversalAfterId == afterId) {
7781            return;
7782        }
7783        mAccessibilityTraversalAfterId = afterId;
7784        notifyViewAccessibilityStateChangedIfNeeded(
7785                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7786    }
7787
7788    /**
7789     * Gets the id of a view after which this one is visited in accessibility traversal.
7790     *
7791     * @return The id of a view this one succeedes in accessibility traversal if
7792     *         specified, otherwise {@link #NO_ID}.
7793     *
7794     * @see #setAccessibilityTraversalAfter(int)
7795     */
7796    public int getAccessibilityTraversalAfter() {
7797        return mAccessibilityTraversalAfterId;
7798    }
7799
7800    /**
7801     * Gets the id of a view for which this view serves as a label for
7802     * accessibility purposes.
7803     *
7804     * @return The labeled view id.
7805     */
7806    @ViewDebug.ExportedProperty(category = "accessibility")
7807    public int getLabelFor() {
7808        return mLabelForId;
7809    }
7810
7811    /**
7812     * Sets the id of a view for which this view serves as a label for
7813     * accessibility purposes.
7814     *
7815     * @param id The labeled view id.
7816     */
7817    @RemotableViewMethod
7818    public void setLabelFor(@IdRes int id) {
7819        if (mLabelForId == id) {
7820            return;
7821        }
7822        mLabelForId = id;
7823        if (mLabelForId != View.NO_ID
7824                && mID == View.NO_ID) {
7825            mID = generateViewId();
7826        }
7827        notifyViewAccessibilityStateChangedIfNeeded(
7828                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7829    }
7830
7831    /**
7832     * Invoked whenever this view loses focus, either by losing window focus or by losing
7833     * focus within its window. This method can be used to clear any state tied to the
7834     * focus. For instance, if a button is held pressed with the trackball and the window
7835     * loses focus, this method can be used to cancel the press.
7836     *
7837     * Subclasses of View overriding this method should always call super.onFocusLost().
7838     *
7839     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
7840     * @see #onWindowFocusChanged(boolean)
7841     *
7842     * @hide pending API council approval
7843     */
7844    @CallSuper
7845    protected void onFocusLost() {
7846        resetPressedState();
7847    }
7848
7849    private void resetPressedState() {
7850        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7851            return;
7852        }
7853
7854        if (isPressed()) {
7855            setPressed(false);
7856
7857            if (!mHasPerformedLongPress) {
7858                removeLongPressCallback();
7859            }
7860        }
7861    }
7862
7863    /**
7864     * Returns true if this view has focus
7865     *
7866     * @return True if this view has focus, false otherwise.
7867     */
7868    @ViewDebug.ExportedProperty(category = "focus")
7869    public boolean isFocused() {
7870        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7871    }
7872
7873    /**
7874     * Find the view in the hierarchy rooted at this view that currently has
7875     * focus.
7876     *
7877     * @return The view that currently has focus, or null if no focused view can
7878     *         be found.
7879     */
7880    public View findFocus() {
7881        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7882    }
7883
7884    /**
7885     * Indicates whether this view is one of the set of scrollable containers in
7886     * its window.
7887     *
7888     * @return whether this view is one of the set of scrollable containers in
7889     * its window
7890     *
7891     * @attr ref android.R.styleable#View_isScrollContainer
7892     */
7893    public boolean isScrollContainer() {
7894        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7895    }
7896
7897    /**
7898     * Change whether this view is one of the set of scrollable containers in
7899     * its window.  This will be used to determine whether the window can
7900     * resize or must pan when a soft input area is open -- scrollable
7901     * containers allow the window to use resize mode since the container
7902     * will appropriately shrink.
7903     *
7904     * @attr ref android.R.styleable#View_isScrollContainer
7905     */
7906    public void setScrollContainer(boolean isScrollContainer) {
7907        if (isScrollContainer) {
7908            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7909                mAttachInfo.mScrollContainers.add(this);
7910                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7911            }
7912            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7913        } else {
7914            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7915                mAttachInfo.mScrollContainers.remove(this);
7916            }
7917            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7918        }
7919    }
7920
7921    /**
7922     * Returns the quality of the drawing cache.
7923     *
7924     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7925     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7926     *
7927     * @see #setDrawingCacheQuality(int)
7928     * @see #setDrawingCacheEnabled(boolean)
7929     * @see #isDrawingCacheEnabled()
7930     *
7931     * @attr ref android.R.styleable#View_drawingCacheQuality
7932     */
7933    @DrawingCacheQuality
7934    public int getDrawingCacheQuality() {
7935        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7936    }
7937
7938    /**
7939     * Set the drawing cache quality of this view. This value is used only when the
7940     * drawing cache is enabled
7941     *
7942     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7943     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7944     *
7945     * @see #getDrawingCacheQuality()
7946     * @see #setDrawingCacheEnabled(boolean)
7947     * @see #isDrawingCacheEnabled()
7948     *
7949     * @attr ref android.R.styleable#View_drawingCacheQuality
7950     */
7951    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7952        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7953    }
7954
7955    /**
7956     * Returns whether the screen should remain on, corresponding to the current
7957     * value of {@link #KEEP_SCREEN_ON}.
7958     *
7959     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7960     *
7961     * @see #setKeepScreenOn(boolean)
7962     *
7963     * @attr ref android.R.styleable#View_keepScreenOn
7964     */
7965    public boolean getKeepScreenOn() {
7966        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7967    }
7968
7969    /**
7970     * Controls whether the screen should remain on, modifying the
7971     * value of {@link #KEEP_SCREEN_ON}.
7972     *
7973     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7974     *
7975     * @see #getKeepScreenOn()
7976     *
7977     * @attr ref android.R.styleable#View_keepScreenOn
7978     */
7979    public void setKeepScreenOn(boolean keepScreenOn) {
7980        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7981    }
7982
7983    /**
7984     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7985     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7986     *
7987     * @attr ref android.R.styleable#View_nextFocusLeft
7988     */
7989    public int getNextFocusLeftId() {
7990        return mNextFocusLeftId;
7991    }
7992
7993    /**
7994     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7995     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7996     * decide automatically.
7997     *
7998     * @attr ref android.R.styleable#View_nextFocusLeft
7999     */
8000    public void setNextFocusLeftId(int nextFocusLeftId) {
8001        mNextFocusLeftId = nextFocusLeftId;
8002    }
8003
8004    /**
8005     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8006     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8007     *
8008     * @attr ref android.R.styleable#View_nextFocusRight
8009     */
8010    public int getNextFocusRightId() {
8011        return mNextFocusRightId;
8012    }
8013
8014    /**
8015     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8016     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8017     * decide automatically.
8018     *
8019     * @attr ref android.R.styleable#View_nextFocusRight
8020     */
8021    public void setNextFocusRightId(int nextFocusRightId) {
8022        mNextFocusRightId = nextFocusRightId;
8023    }
8024
8025    /**
8026     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8027     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8028     *
8029     * @attr ref android.R.styleable#View_nextFocusUp
8030     */
8031    public int getNextFocusUpId() {
8032        return mNextFocusUpId;
8033    }
8034
8035    /**
8036     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8037     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8038     * decide automatically.
8039     *
8040     * @attr ref android.R.styleable#View_nextFocusUp
8041     */
8042    public void setNextFocusUpId(int nextFocusUpId) {
8043        mNextFocusUpId = nextFocusUpId;
8044    }
8045
8046    /**
8047     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8048     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8049     *
8050     * @attr ref android.R.styleable#View_nextFocusDown
8051     */
8052    public int getNextFocusDownId() {
8053        return mNextFocusDownId;
8054    }
8055
8056    /**
8057     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8058     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8059     * decide automatically.
8060     *
8061     * @attr ref android.R.styleable#View_nextFocusDown
8062     */
8063    public void setNextFocusDownId(int nextFocusDownId) {
8064        mNextFocusDownId = nextFocusDownId;
8065    }
8066
8067    /**
8068     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8069     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8070     *
8071     * @attr ref android.R.styleable#View_nextFocusForward
8072     */
8073    public int getNextFocusForwardId() {
8074        return mNextFocusForwardId;
8075    }
8076
8077    /**
8078     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8079     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8080     * decide automatically.
8081     *
8082     * @attr ref android.R.styleable#View_nextFocusForward
8083     */
8084    public void setNextFocusForwardId(int nextFocusForwardId) {
8085        mNextFocusForwardId = nextFocusForwardId;
8086    }
8087
8088    /**
8089     * Gets the id of the root of the next keyboard navigation cluster.
8090     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8091     * decide automatically.
8092     *
8093     * @attr ref android.R.styleable#View_nextClusterForward
8094     */
8095    public int getNextClusterForwardId() {
8096        return mNextClusterForwardId;
8097    }
8098
8099    /**
8100     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8101     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8102     * decide automatically.
8103     *
8104     * @attr ref android.R.styleable#View_nextClusterForward
8105     */
8106    public void setNextClusterForwardId(int nextClusterForwardId) {
8107        mNextClusterForwardId = nextClusterForwardId;
8108    }
8109
8110    /**
8111     * Returns the visibility of this view and all of its ancestors
8112     *
8113     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8114     */
8115    public boolean isShown() {
8116        View current = this;
8117        //noinspection ConstantConditions
8118        do {
8119            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8120                return false;
8121            }
8122            ViewParent parent = current.mParent;
8123            if (parent == null) {
8124                return false; // We are not attached to the view root
8125            }
8126            if (!(parent instanceof View)) {
8127                return true;
8128            }
8129            current = (View) parent;
8130        } while (current != null);
8131
8132        return false;
8133    }
8134
8135    /**
8136     * Called by the view hierarchy when the content insets for a window have
8137     * changed, to allow it to adjust its content to fit within those windows.
8138     * The content insets tell you the space that the status bar, input method,
8139     * and other system windows infringe on the application's window.
8140     *
8141     * <p>You do not normally need to deal with this function, since the default
8142     * window decoration given to applications takes care of applying it to the
8143     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8144     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8145     * and your content can be placed under those system elements.  You can then
8146     * use this method within your view hierarchy if you have parts of your UI
8147     * which you would like to ensure are not being covered.
8148     *
8149     * <p>The default implementation of this method simply applies the content
8150     * insets to the view's padding, consuming that content (modifying the
8151     * insets to be 0), and returning true.  This behavior is off by default, but can
8152     * be enabled through {@link #setFitsSystemWindows(boolean)}.
8153     *
8154     * <p>This function's traversal down the hierarchy is depth-first.  The same content
8155     * insets object is propagated down the hierarchy, so any changes made to it will
8156     * be seen by all following views (including potentially ones above in
8157     * the hierarchy since this is a depth-first traversal).  The first view
8158     * that returns true will abort the entire traversal.
8159     *
8160     * <p>The default implementation works well for a situation where it is
8161     * used with a container that covers the entire window, allowing it to
8162     * apply the appropriate insets to its content on all edges.  If you need
8163     * a more complicated layout (such as two different views fitting system
8164     * windows, one on the top of the window, and one on the bottom),
8165     * you can override the method and handle the insets however you would like.
8166     * Note that the insets provided by the framework are always relative to the
8167     * far edges of the window, not accounting for the location of the called view
8168     * within that window.  (In fact when this method is called you do not yet know
8169     * where the layout will place the view, as it is done before layout happens.)
8170     *
8171     * <p>Note: unlike many View methods, there is no dispatch phase to this
8172     * call.  If you are overriding it in a ViewGroup and want to allow the
8173     * call to continue to your children, you must be sure to call the super
8174     * implementation.
8175     *
8176     * <p>Here is a sample layout that makes use of fitting system windows
8177     * to have controls for a video view placed inside of the window decorations
8178     * that it hides and shows.  This can be used with code like the second
8179     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8180     *
8181     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8182     *
8183     * @param insets Current content insets of the window.  Prior to
8184     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8185     * the insets or else you and Android will be unhappy.
8186     *
8187     * @return {@code true} if this view applied the insets and it should not
8188     * continue propagating further down the hierarchy, {@code false} otherwise.
8189     * @see #getFitsSystemWindows()
8190     * @see #setFitsSystemWindows(boolean)
8191     * @see #setSystemUiVisibility(int)
8192     *
8193     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8194     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8195     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8196     * to implement handling their own insets.
8197     */
8198    @Deprecated
8199    protected boolean fitSystemWindows(Rect insets) {
8200        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8201            if (insets == null) {
8202                // Null insets by definition have already been consumed.
8203                // This call cannot apply insets since there are none to apply,
8204                // so return false.
8205                return false;
8206            }
8207            // If we're not in the process of dispatching the newer apply insets call,
8208            // that means we're not in the compatibility path. Dispatch into the newer
8209            // apply insets path and take things from there.
8210            try {
8211                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8212                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8213            } finally {
8214                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8215            }
8216        } else {
8217            // We're being called from the newer apply insets path.
8218            // Perform the standard fallback behavior.
8219            return fitSystemWindowsInt(insets);
8220        }
8221    }
8222
8223    private boolean fitSystemWindowsInt(Rect insets) {
8224        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8225            mUserPaddingStart = UNDEFINED_PADDING;
8226            mUserPaddingEnd = UNDEFINED_PADDING;
8227            Rect localInsets = sThreadLocal.get();
8228            if (localInsets == null) {
8229                localInsets = new Rect();
8230                sThreadLocal.set(localInsets);
8231            }
8232            boolean res = computeFitSystemWindows(insets, localInsets);
8233            mUserPaddingLeftInitial = localInsets.left;
8234            mUserPaddingRightInitial = localInsets.right;
8235            internalSetPadding(localInsets.left, localInsets.top,
8236                    localInsets.right, localInsets.bottom);
8237            return res;
8238        }
8239        return false;
8240    }
8241
8242    /**
8243     * Called when the view should apply {@link WindowInsets} according to its internal policy.
8244     *
8245     * <p>This method should be overridden by views that wish to apply a policy different from or
8246     * in addition to the default behavior. Clients that wish to force a view subtree
8247     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8248     *
8249     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8250     * it will be called during dispatch instead of this method. The listener may optionally
8251     * call this method from its own implementation if it wishes to apply the view's default
8252     * insets policy in addition to its own.</p>
8253     *
8254     * <p>Implementations of this method should either return the insets parameter unchanged
8255     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8256     * that this view applied itself. This allows new inset types added in future platform
8257     * versions to pass through existing implementations unchanged without being erroneously
8258     * consumed.</p>
8259     *
8260     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8261     * property is set then the view will consume the system window insets and apply them
8262     * as padding for the view.</p>
8263     *
8264     * @param insets Insets to apply
8265     * @return The supplied insets with any applied insets consumed
8266     */
8267    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8268        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8269            // We weren't called from within a direct call to fitSystemWindows,
8270            // call into it as a fallback in case we're in a class that overrides it
8271            // and has logic to perform.
8272            if (fitSystemWindows(insets.getSystemWindowInsets())) {
8273                return insets.consumeSystemWindowInsets();
8274            }
8275        } else {
8276            // We were called from within a direct call to fitSystemWindows.
8277            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8278                return insets.consumeSystemWindowInsets();
8279            }
8280        }
8281        return insets;
8282    }
8283
8284    /**
8285     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8286     * window insets to this view. The listener's
8287     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8288     * method will be called instead of the view's
8289     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8290     *
8291     * @param listener Listener to set
8292     *
8293     * @see #onApplyWindowInsets(WindowInsets)
8294     */
8295    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8296        getListenerInfo().mOnApplyWindowInsetsListener = listener;
8297    }
8298
8299    /**
8300     * Request to apply the given window insets to this view or another view in its subtree.
8301     *
8302     * <p>This method should be called by clients wishing to apply insets corresponding to areas
8303     * obscured by window decorations or overlays. This can include the status and navigation bars,
8304     * action bars, input methods and more. New inset categories may be added in the future.
8305     * The method returns the insets provided minus any that were applied by this view or its
8306     * children.</p>
8307     *
8308     * <p>Clients wishing to provide custom behavior should override the
8309     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8310     * {@link OnApplyWindowInsetsListener} via the
8311     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8312     * method.</p>
8313     *
8314     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8315     * </p>
8316     *
8317     * @param insets Insets to apply
8318     * @return The provided insets minus the insets that were consumed
8319     */
8320    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8321        try {
8322            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8323            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8324                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8325            } else {
8326                return onApplyWindowInsets(insets);
8327            }
8328        } finally {
8329            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
8330        }
8331    }
8332
8333    /**
8334     * Compute the view's coordinate within the surface.
8335     *
8336     * <p>Computes the coordinates of this view in its surface. The argument
8337     * must be an array of two integers. After the method returns, the array
8338     * contains the x and y location in that order.</p>
8339     * @hide
8340     * @param location an array of two integers in which to hold the coordinates
8341     */
8342    public void getLocationInSurface(@Size(2) int[] location) {
8343        getLocationInWindow(location);
8344        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
8345            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
8346            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
8347        }
8348    }
8349
8350    /**
8351     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
8352     * only available if the view is attached.
8353     *
8354     * @return WindowInsets from the top of the view hierarchy or null if View is detached
8355     */
8356    public WindowInsets getRootWindowInsets() {
8357        if (mAttachInfo != null) {
8358            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
8359        }
8360        return null;
8361    }
8362
8363    /**
8364     * @hide Compute the insets that should be consumed by this view and the ones
8365     * that should propagate to those under it.
8366     */
8367    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
8368        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8369                || mAttachInfo == null
8370                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
8371                        && !mAttachInfo.mOverscanRequested)) {
8372            outLocalInsets.set(inoutInsets);
8373            inoutInsets.set(0, 0, 0, 0);
8374            return true;
8375        } else {
8376            // The application wants to take care of fitting system window for
8377            // the content...  however we still need to take care of any overscan here.
8378            final Rect overscan = mAttachInfo.mOverscanInsets;
8379            outLocalInsets.set(overscan);
8380            inoutInsets.left -= overscan.left;
8381            inoutInsets.top -= overscan.top;
8382            inoutInsets.right -= overscan.right;
8383            inoutInsets.bottom -= overscan.bottom;
8384            return false;
8385        }
8386    }
8387
8388    /**
8389     * Compute insets that should be consumed by this view and the ones that should propagate
8390     * to those under it.
8391     *
8392     * @param in Insets currently being processed by this View, likely received as a parameter
8393     *           to {@link #onApplyWindowInsets(WindowInsets)}.
8394     * @param outLocalInsets A Rect that will receive the insets that should be consumed
8395     *                       by this view
8396     * @return Insets that should be passed along to views under this one
8397     */
8398    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
8399        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8400                || mAttachInfo == null
8401                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
8402            outLocalInsets.set(in.getSystemWindowInsets());
8403            return in.consumeSystemWindowInsets();
8404        } else {
8405            outLocalInsets.set(0, 0, 0, 0);
8406            return in;
8407        }
8408    }
8409
8410    /**
8411     * Sets whether or not this view should account for system screen decorations
8412     * such as the status bar and inset its content; that is, controlling whether
8413     * the default implementation of {@link #fitSystemWindows(Rect)} will be
8414     * executed.  See that method for more details.
8415     *
8416     * <p>Note that if you are providing your own implementation of
8417     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
8418     * flag to true -- your implementation will be overriding the default
8419     * implementation that checks this flag.
8420     *
8421     * @param fitSystemWindows If true, then the default implementation of
8422     * {@link #fitSystemWindows(Rect)} will be executed.
8423     *
8424     * @attr ref android.R.styleable#View_fitsSystemWindows
8425     * @see #getFitsSystemWindows()
8426     * @see #fitSystemWindows(Rect)
8427     * @see #setSystemUiVisibility(int)
8428     */
8429    public void setFitsSystemWindows(boolean fitSystemWindows) {
8430        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
8431    }
8432
8433    /**
8434     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
8435     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
8436     * will be executed.
8437     *
8438     * @return {@code true} if the default implementation of
8439     * {@link #fitSystemWindows(Rect)} will be executed.
8440     *
8441     * @attr ref android.R.styleable#View_fitsSystemWindows
8442     * @see #setFitsSystemWindows(boolean)
8443     * @see #fitSystemWindows(Rect)
8444     * @see #setSystemUiVisibility(int)
8445     */
8446    @ViewDebug.ExportedProperty
8447    public boolean getFitsSystemWindows() {
8448        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8449    }
8450
8451    /** @hide */
8452    public boolean fitsSystemWindows() {
8453        return getFitsSystemWindows();
8454    }
8455
8456    /**
8457     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8458     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8459     */
8460    @Deprecated
8461    public void requestFitSystemWindows() {
8462        if (mParent != null) {
8463            mParent.requestFitSystemWindows();
8464        }
8465    }
8466
8467    /**
8468     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8469     */
8470    public void requestApplyInsets() {
8471        requestFitSystemWindows();
8472    }
8473
8474    /**
8475     * For use by PhoneWindow to make its own system window fitting optional.
8476     * @hide
8477     */
8478    public void makeOptionalFitsSystemWindows() {
8479        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8480    }
8481
8482    /**
8483     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8484     * treat them as such.
8485     * @hide
8486     */
8487    public void getOutsets(Rect outOutsetRect) {
8488        if (mAttachInfo != null) {
8489            outOutsetRect.set(mAttachInfo.mOutsets);
8490        } else {
8491            outOutsetRect.setEmpty();
8492        }
8493    }
8494
8495    /**
8496     * Returns the visibility status for this view.
8497     *
8498     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8499     * @attr ref android.R.styleable#View_visibility
8500     */
8501    @ViewDebug.ExportedProperty(mapping = {
8502        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
8503        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
8504        @ViewDebug.IntToString(from = GONE,      to = "GONE")
8505    })
8506    @Visibility
8507    public int getVisibility() {
8508        return mViewFlags & VISIBILITY_MASK;
8509    }
8510
8511    /**
8512     * Set the visibility state of this view.
8513     *
8514     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8515     * @attr ref android.R.styleable#View_visibility
8516     */
8517    @RemotableViewMethod
8518    public void setVisibility(@Visibility int visibility) {
8519        setFlags(visibility, VISIBILITY_MASK);
8520    }
8521
8522    /**
8523     * Returns the enabled status for this view. The interpretation of the
8524     * enabled state varies by subclass.
8525     *
8526     * @return True if this view is enabled, false otherwise.
8527     */
8528    @ViewDebug.ExportedProperty
8529    public boolean isEnabled() {
8530        return (mViewFlags & ENABLED_MASK) == ENABLED;
8531    }
8532
8533    /**
8534     * Set the enabled state of this view. The interpretation of the enabled
8535     * state varies by subclass.
8536     *
8537     * @param enabled True if this view is enabled, false otherwise.
8538     */
8539    @RemotableViewMethod
8540    public void setEnabled(boolean enabled) {
8541        if (enabled == isEnabled()) return;
8542
8543        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
8544
8545        /*
8546         * The View most likely has to change its appearance, so refresh
8547         * the drawable state.
8548         */
8549        refreshDrawableState();
8550
8551        // Invalidate too, since the default behavior for views is to be
8552        // be drawn at 50% alpha rather than to change the drawable.
8553        invalidate(true);
8554
8555        if (!enabled) {
8556            cancelPendingInputEvents();
8557        }
8558    }
8559
8560    /**
8561     * Set whether this view can receive the focus.
8562     * <p>
8563     * Setting this to false will also ensure that this view is not focusable
8564     * in touch mode.
8565     *
8566     * @param focusable If true, this view can receive the focus.
8567     *
8568     * @see #setFocusableInTouchMode(boolean)
8569     * @see #setFocusable(int)
8570     * @attr ref android.R.styleable#View_focusable
8571     */
8572    public void setFocusable(boolean focusable) {
8573        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
8574    }
8575
8576    /**
8577     * Sets whether this view can receive focus.
8578     * <p>
8579     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
8580     * automatically based on the view's interactivity. This is the default.
8581     * <p>
8582     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
8583     * in touch mode.
8584     *
8585     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
8586     *                  or {@link #FOCUSABLE_AUTO}.
8587     * @see #setFocusableInTouchMode(boolean)
8588     * @attr ref android.R.styleable#View_focusable
8589     */
8590    public void setFocusable(@Focusable int focusable) {
8591        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
8592            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
8593        }
8594        setFlags(focusable, FOCUSABLE_MASK);
8595    }
8596
8597    /**
8598     * Set whether this view can receive focus while in touch mode.
8599     *
8600     * Setting this to true will also ensure that this view is focusable.
8601     *
8602     * @param focusableInTouchMode If true, this view can receive the focus while
8603     *   in touch mode.
8604     *
8605     * @see #setFocusable(boolean)
8606     * @attr ref android.R.styleable#View_focusableInTouchMode
8607     */
8608    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
8609        // Focusable in touch mode should always be set before the focusable flag
8610        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
8611        // which, in touch mode, will not successfully request focus on this view
8612        // because the focusable in touch mode flag is not set
8613        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
8614        if (focusableInTouchMode) {
8615            setFlags(FOCUSABLE, FOCUSABLE_MASK);
8616        }
8617    }
8618
8619    /**
8620     * Set whether this view should have sound effects enabled for events such as
8621     * clicking and touching.
8622     *
8623     * <p>You may wish to disable sound effects for a view if you already play sounds,
8624     * for instance, a dial key that plays dtmf tones.
8625     *
8626     * @param soundEffectsEnabled whether sound effects are enabled for this view.
8627     * @see #isSoundEffectsEnabled()
8628     * @see #playSoundEffect(int)
8629     * @attr ref android.R.styleable#View_soundEffectsEnabled
8630     */
8631    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
8632        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
8633    }
8634
8635    /**
8636     * @return whether this view should have sound effects enabled for events such as
8637     *     clicking and touching.
8638     *
8639     * @see #setSoundEffectsEnabled(boolean)
8640     * @see #playSoundEffect(int)
8641     * @attr ref android.R.styleable#View_soundEffectsEnabled
8642     */
8643    @ViewDebug.ExportedProperty
8644    public boolean isSoundEffectsEnabled() {
8645        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
8646    }
8647
8648    /**
8649     * Set whether this view should have haptic feedback for events such as
8650     * long presses.
8651     *
8652     * <p>You may wish to disable haptic feedback if your view already controls
8653     * its own haptic feedback.
8654     *
8655     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
8656     * @see #isHapticFeedbackEnabled()
8657     * @see #performHapticFeedback(int)
8658     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8659     */
8660    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
8661        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
8662    }
8663
8664    /**
8665     * @return whether this view should have haptic feedback enabled for events
8666     * long presses.
8667     *
8668     * @see #setHapticFeedbackEnabled(boolean)
8669     * @see #performHapticFeedback(int)
8670     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
8671     */
8672    @ViewDebug.ExportedProperty
8673    public boolean isHapticFeedbackEnabled() {
8674        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
8675    }
8676
8677    /**
8678     * Returns the layout direction for this view.
8679     *
8680     * @return One of {@link #LAYOUT_DIRECTION_LTR},
8681     *   {@link #LAYOUT_DIRECTION_RTL},
8682     *   {@link #LAYOUT_DIRECTION_INHERIT} or
8683     *   {@link #LAYOUT_DIRECTION_LOCALE}.
8684     *
8685     * @attr ref android.R.styleable#View_layoutDirection
8686     *
8687     * @hide
8688     */
8689    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8690        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
8691        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
8692        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
8693        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
8694    })
8695    @LayoutDir
8696    public int getRawLayoutDirection() {
8697        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
8698    }
8699
8700    /**
8701     * Set the layout direction for this view. This will propagate a reset of layout direction
8702     * resolution to the view's children and resolve layout direction for this view.
8703     *
8704     * @param layoutDirection the layout direction to set. Should be one of:
8705     *
8706     * {@link #LAYOUT_DIRECTION_LTR},
8707     * {@link #LAYOUT_DIRECTION_RTL},
8708     * {@link #LAYOUT_DIRECTION_INHERIT},
8709     * {@link #LAYOUT_DIRECTION_LOCALE}.
8710     *
8711     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
8712     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
8713     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
8714     *
8715     * @attr ref android.R.styleable#View_layoutDirection
8716     */
8717    @RemotableViewMethod
8718    public void setLayoutDirection(@LayoutDir int layoutDirection) {
8719        if (getRawLayoutDirection() != layoutDirection) {
8720            // Reset the current layout direction and the resolved one
8721            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
8722            resetRtlProperties();
8723            // Set the new layout direction (filtered)
8724            mPrivateFlags2 |=
8725                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
8726            // We need to resolve all RTL properties as they all depend on layout direction
8727            resolveRtlPropertiesIfNeeded();
8728            requestLayout();
8729            invalidate(true);
8730        }
8731    }
8732
8733    /**
8734     * Returns the resolved layout direction for this view.
8735     *
8736     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
8737     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
8738     *
8739     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
8740     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
8741     *
8742     * @attr ref android.R.styleable#View_layoutDirection
8743     */
8744    @ViewDebug.ExportedProperty(category = "layout", mapping = {
8745        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
8746        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
8747    })
8748    @ResolvedLayoutDir
8749    public int getLayoutDirection() {
8750        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
8751        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
8752            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
8753            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
8754        }
8755        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
8756                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
8757    }
8758
8759    /**
8760     * Indicates whether or not this view's layout is right-to-left. This is resolved from
8761     * layout attribute and/or the inherited value from the parent
8762     *
8763     * @return true if the layout is right-to-left.
8764     *
8765     * @hide
8766     */
8767    @ViewDebug.ExportedProperty(category = "layout")
8768    public boolean isLayoutRtl() {
8769        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
8770    }
8771
8772    /**
8773     * Indicates whether the view is currently tracking transient state that the
8774     * app should not need to concern itself with saving and restoring, but that
8775     * the framework should take special note to preserve when possible.
8776     *
8777     * <p>A view with transient state cannot be trivially rebound from an external
8778     * data source, such as an adapter binding item views in a list. This may be
8779     * because the view is performing an animation, tracking user selection
8780     * of content, or similar.</p>
8781     *
8782     * @return true if the view has transient state
8783     */
8784    @ViewDebug.ExportedProperty(category = "layout")
8785    public boolean hasTransientState() {
8786        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
8787    }
8788
8789    /**
8790     * Set whether this view is currently tracking transient state that the
8791     * framework should attempt to preserve when possible. This flag is reference counted,
8792     * so every call to setHasTransientState(true) should be paired with a later call
8793     * to setHasTransientState(false).
8794     *
8795     * <p>A view with transient state cannot be trivially rebound from an external
8796     * data source, such as an adapter binding item views in a list. This may be
8797     * because the view is performing an animation, tracking user selection
8798     * of content, or similar.</p>
8799     *
8800     * @param hasTransientState true if this view has transient state
8801     */
8802    public void setHasTransientState(boolean hasTransientState) {
8803        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
8804                mTransientStateCount - 1;
8805        if (mTransientStateCount < 0) {
8806            mTransientStateCount = 0;
8807            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
8808                    "unmatched pair of setHasTransientState calls");
8809        } else if ((hasTransientState && mTransientStateCount == 1) ||
8810                (!hasTransientState && mTransientStateCount == 0)) {
8811            // update flag if we've just incremented up from 0 or decremented down to 0
8812            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
8813                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
8814            if (mParent != null) {
8815                try {
8816                    mParent.childHasTransientStateChanged(this, hasTransientState);
8817                } catch (AbstractMethodError e) {
8818                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8819                            " does not fully implement ViewParent", e);
8820                }
8821            }
8822        }
8823    }
8824
8825    /**
8826     * Returns true if this view is currently attached to a window.
8827     */
8828    public boolean isAttachedToWindow() {
8829        return mAttachInfo != null;
8830    }
8831
8832    /**
8833     * Returns true if this view has been through at least one layout since it
8834     * was last attached to or detached from a window.
8835     */
8836    public boolean isLaidOut() {
8837        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
8838    }
8839
8840    /**
8841     * If this view doesn't do any drawing on its own, set this flag to
8842     * allow further optimizations. By default, this flag is not set on
8843     * View, but could be set on some View subclasses such as ViewGroup.
8844     *
8845     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
8846     * you should clear this flag.
8847     *
8848     * @param willNotDraw whether or not this View draw on its own
8849     */
8850    public void setWillNotDraw(boolean willNotDraw) {
8851        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
8852    }
8853
8854    /**
8855     * Returns whether or not this View draws on its own.
8856     *
8857     * @return true if this view has nothing to draw, false otherwise
8858     */
8859    @ViewDebug.ExportedProperty(category = "drawing")
8860    public boolean willNotDraw() {
8861        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
8862    }
8863
8864    /**
8865     * When a View's drawing cache is enabled, drawing is redirected to an
8866     * offscreen bitmap. Some views, like an ImageView, must be able to
8867     * bypass this mechanism if they already draw a single bitmap, to avoid
8868     * unnecessary usage of the memory.
8869     *
8870     * @param willNotCacheDrawing true if this view does not cache its
8871     *        drawing, false otherwise
8872     */
8873    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
8874        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
8875    }
8876
8877    /**
8878     * Returns whether or not this View can cache its drawing or not.
8879     *
8880     * @return true if this view does not cache its drawing, false otherwise
8881     */
8882    @ViewDebug.ExportedProperty(category = "drawing")
8883    public boolean willNotCacheDrawing() {
8884        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
8885    }
8886
8887    /**
8888     * Indicates whether this view reacts to click events or not.
8889     *
8890     * @return true if the view is clickable, false otherwise
8891     *
8892     * @see #setClickable(boolean)
8893     * @attr ref android.R.styleable#View_clickable
8894     */
8895    @ViewDebug.ExportedProperty
8896    public boolean isClickable() {
8897        return (mViewFlags & CLICKABLE) == CLICKABLE;
8898    }
8899
8900    /**
8901     * Enables or disables click events for this view. When a view
8902     * is clickable it will change its state to "pressed" on every click.
8903     * Subclasses should set the view clickable to visually react to
8904     * user's clicks.
8905     *
8906     * @param clickable true to make the view clickable, false otherwise
8907     *
8908     * @see #isClickable()
8909     * @attr ref android.R.styleable#View_clickable
8910     */
8911    public void setClickable(boolean clickable) {
8912        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8913    }
8914
8915    /**
8916     * Indicates whether this view reacts to long click events or not.
8917     *
8918     * @return true if the view is long clickable, false otherwise
8919     *
8920     * @see #setLongClickable(boolean)
8921     * @attr ref android.R.styleable#View_longClickable
8922     */
8923    public boolean isLongClickable() {
8924        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8925    }
8926
8927    /**
8928     * Enables or disables long click events for this view. When a view is long
8929     * clickable it reacts to the user holding down the button for a longer
8930     * duration than a tap. This event can either launch the listener or a
8931     * context menu.
8932     *
8933     * @param longClickable true to make the view long clickable, false otherwise
8934     * @see #isLongClickable()
8935     * @attr ref android.R.styleable#View_longClickable
8936     */
8937    public void setLongClickable(boolean longClickable) {
8938        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8939    }
8940
8941    /**
8942     * Indicates whether this view reacts to context clicks or not.
8943     *
8944     * @return true if the view is context clickable, false otherwise
8945     * @see #setContextClickable(boolean)
8946     * @attr ref android.R.styleable#View_contextClickable
8947     */
8948    public boolean isContextClickable() {
8949        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8950    }
8951
8952    /**
8953     * Enables or disables context clicking for this view. This event can launch the listener.
8954     *
8955     * @param contextClickable true to make the view react to a context click, false otherwise
8956     * @see #isContextClickable()
8957     * @attr ref android.R.styleable#View_contextClickable
8958     */
8959    public void setContextClickable(boolean contextClickable) {
8960        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8961    }
8962
8963    /**
8964     * Sets the pressed state for this view and provides a touch coordinate for
8965     * animation hinting.
8966     *
8967     * @param pressed Pass true to set the View's internal state to "pressed",
8968     *            or false to reverts the View's internal state from a
8969     *            previously set "pressed" state.
8970     * @param x The x coordinate of the touch that caused the press
8971     * @param y The y coordinate of the touch that caused the press
8972     */
8973    private void setPressed(boolean pressed, float x, float y) {
8974        if (pressed) {
8975            drawableHotspotChanged(x, y);
8976        }
8977
8978        setPressed(pressed);
8979    }
8980
8981    /**
8982     * Sets the pressed state for this view.
8983     *
8984     * @see #isClickable()
8985     * @see #setClickable(boolean)
8986     *
8987     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8988     *        the View's internal state from a previously set "pressed" state.
8989     */
8990    public void setPressed(boolean pressed) {
8991        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8992
8993        if (pressed) {
8994            mPrivateFlags |= PFLAG_PRESSED;
8995        } else {
8996            mPrivateFlags &= ~PFLAG_PRESSED;
8997        }
8998
8999        if (needsRefresh) {
9000            refreshDrawableState();
9001        }
9002        dispatchSetPressed(pressed);
9003    }
9004
9005    /**
9006     * Dispatch setPressed to all of this View's children.
9007     *
9008     * @see #setPressed(boolean)
9009     *
9010     * @param pressed The new pressed state
9011     */
9012    protected void dispatchSetPressed(boolean pressed) {
9013    }
9014
9015    /**
9016     * Indicates whether the view is currently in pressed state. Unless
9017     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9018     * the pressed state.
9019     *
9020     * @see #setPressed(boolean)
9021     * @see #isClickable()
9022     * @see #setClickable(boolean)
9023     *
9024     * @return true if the view is currently pressed, false otherwise
9025     */
9026    @ViewDebug.ExportedProperty
9027    public boolean isPressed() {
9028        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9029    }
9030
9031    /**
9032     * @hide
9033     * Indicates whether this view will participate in data collection through
9034     * {@link ViewStructure}.  If true, it will not provide any data
9035     * for itself or its children.  If false, the normal data collection will be allowed.
9036     *
9037     * @return Returns false if assist data collection is not blocked, else true.
9038     *
9039     * @see #setAssistBlocked(boolean)
9040     * @attr ref android.R.styleable#View_assistBlocked
9041     */
9042    public boolean isAssistBlocked() {
9043        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9044    }
9045
9046    /**
9047     * @hide
9048     * Indicates whether this view will participate in data collection through
9049     * {@link ViewStructure} for auto-fill purposes.
9050     *
9051     * <p>If {@code true}, it will not provide any data for itself or its children.
9052     * <p>If {@code false}, the normal data collection will be allowed.
9053     *
9054     * @return Returns {@code false} if assist data collection for auto-fill is not blocked,
9055     * else {@code true}.
9056     *
9057     * TODO(b/33197203): update / remove javadoc tags below
9058     * @see #setAssistBlocked(boolean)
9059     * @attr ref android.R.styleable#View_assistBlocked
9060     */
9061    public boolean isAutoFillBlocked() {
9062        return false; // TODO(b/33197203): properly implement it
9063    }
9064
9065    /**
9066     * @hide
9067     * Controls whether assist data collection from this view and its children is enabled
9068     * (that is, whether {@link #onProvideStructure} and
9069     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9070     * allowing normal assist collection.  Setting this to false will disable assist collection.
9071     *
9072     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9073     * (the default) to allow it.
9074     *
9075     * @see #isAssistBlocked()
9076     * @see #onProvideStructure
9077     * @see #onProvideVirtualStructure
9078     * @attr ref android.R.styleable#View_assistBlocked
9079     */
9080    public void setAssistBlocked(boolean enabled) {
9081        if (enabled) {
9082            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9083        } else {
9084            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9085        }
9086    }
9087
9088    /**
9089     * Indicates whether this view will save its state (that is,
9090     * whether its {@link #onSaveInstanceState} method will be called).
9091     *
9092     * @return Returns true if the view state saving is enabled, else false.
9093     *
9094     * @see #setSaveEnabled(boolean)
9095     * @attr ref android.R.styleable#View_saveEnabled
9096     */
9097    public boolean isSaveEnabled() {
9098        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9099    }
9100
9101    /**
9102     * Controls whether the saving of this view's state is
9103     * enabled (that is, whether its {@link #onSaveInstanceState} method
9104     * will be called).  Note that even if freezing is enabled, the
9105     * view still must have an id assigned to it (via {@link #setId(int)})
9106     * for its state to be saved.  This flag can only disable the
9107     * saving of this view; any child views may still have their state saved.
9108     *
9109     * @param enabled Set to false to <em>disable</em> state saving, or true
9110     * (the default) to allow it.
9111     *
9112     * @see #isSaveEnabled()
9113     * @see #setId(int)
9114     * @see #onSaveInstanceState()
9115     * @attr ref android.R.styleable#View_saveEnabled
9116     */
9117    public void setSaveEnabled(boolean enabled) {
9118        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
9119    }
9120
9121    /**
9122     * Gets whether the framework should discard touches when the view's
9123     * window is obscured by another visible window.
9124     * Refer to the {@link View} security documentation for more details.
9125     *
9126     * @return True if touch filtering is enabled.
9127     *
9128     * @see #setFilterTouchesWhenObscured(boolean)
9129     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9130     */
9131    @ViewDebug.ExportedProperty
9132    public boolean getFilterTouchesWhenObscured() {
9133        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
9134    }
9135
9136    /**
9137     * Sets whether the framework should discard touches when the view's
9138     * window is obscured by another visible window.
9139     * Refer to the {@link View} security documentation for more details.
9140     *
9141     * @param enabled True if touch filtering should be enabled.
9142     *
9143     * @see #getFilterTouchesWhenObscured
9144     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9145     */
9146    public void setFilterTouchesWhenObscured(boolean enabled) {
9147        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
9148                FILTER_TOUCHES_WHEN_OBSCURED);
9149    }
9150
9151    /**
9152     * Indicates whether the entire hierarchy under this view will save its
9153     * state when a state saving traversal occurs from its parent.  The default
9154     * is true; if false, these views will not be saved unless
9155     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9156     *
9157     * @return Returns true if the view state saving from parent is enabled, else false.
9158     *
9159     * @see #setSaveFromParentEnabled(boolean)
9160     */
9161    public boolean isSaveFromParentEnabled() {
9162        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
9163    }
9164
9165    /**
9166     * Controls whether the entire hierarchy under this view will save its
9167     * state when a state saving traversal occurs from its parent.  The default
9168     * is true; if false, these views will not be saved unless
9169     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9170     *
9171     * @param enabled Set to false to <em>disable</em> state saving, or true
9172     * (the default) to allow it.
9173     *
9174     * @see #isSaveFromParentEnabled()
9175     * @see #setId(int)
9176     * @see #onSaveInstanceState()
9177     */
9178    public void setSaveFromParentEnabled(boolean enabled) {
9179        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
9180    }
9181
9182
9183    /**
9184     * Returns whether this View is currently able to take focus.
9185     *
9186     * @return True if this view can take focus, or false otherwise.
9187     */
9188    @ViewDebug.ExportedProperty(category = "focus")
9189    public final boolean isFocusable() {
9190        return FOCUSABLE == (mViewFlags & FOCUSABLE);
9191    }
9192
9193    /**
9194     * Returns the focusable setting for this view.
9195     *
9196     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
9197     * @attr ref android.R.styleable#View_focusable
9198     */
9199    @ViewDebug.ExportedProperty(mapping = {
9200            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
9201            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
9202            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
9203            })
9204    @Focusable
9205    public int getFocusable() {
9206        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
9207    }
9208
9209    /**
9210     * When a view is focusable, it may not want to take focus when in touch mode.
9211     * For example, a button would like focus when the user is navigating via a D-pad
9212     * so that the user can click on it, but once the user starts touching the screen,
9213     * the button shouldn't take focus
9214     * @return Whether the view is focusable in touch mode.
9215     * @attr ref android.R.styleable#View_focusableInTouchMode
9216     */
9217    @ViewDebug.ExportedProperty
9218    public final boolean isFocusableInTouchMode() {
9219        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9220    }
9221
9222    /**
9223     * Find the nearest view in the specified direction that can take focus.
9224     * This does not actually give focus to that view.
9225     *
9226     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9227     *
9228     * @return The nearest focusable in the specified direction, or null if none
9229     *         can be found.
9230     */
9231    public View focusSearch(@FocusRealDirection int direction) {
9232        if (mParent != null) {
9233            return mParent.focusSearch(this, direction);
9234        } else {
9235            return null;
9236        }
9237    }
9238
9239    /**
9240     * Returns whether this View is a root of a keyboard navigation cluster.
9241     *
9242     * @return True if this view is a root of a cluster, or false otherwise.
9243     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9244     */
9245    @ViewDebug.ExportedProperty(category = "keyboardNavigationCluster")
9246    public final boolean isKeyboardNavigationCluster() {
9247        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9248    }
9249
9250    /**
9251     * Set whether this view is a root of a keyboard navigation cluster.
9252     *
9253     * @param isCluster If true, this view is a root of a cluster.
9254     *
9255     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9256     */
9257    public void setKeyboardNavigationCluster(boolean isCluster) {
9258        if (isCluster) {
9259            mPrivateFlags3 |= PFLAG3_CLUSTER;
9260        } else {
9261            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9262        }
9263    }
9264
9265    /**
9266     * Sets this View as the one which receives focus the next time cluster navigation jumps
9267     * to the cluster containing this View. This does NOT change focus even if the cluster
9268     * containing this view is current.
9269     *
9270     * @hide
9271     */
9272    public void setFocusedInCluster() {
9273        if (mParent instanceof ViewGroup) {
9274            ((ViewGroup) mParent).setFocusInCluster(this);
9275        }
9276    }
9277
9278    /**
9279     * Returns whether this View should receive focus when the focus is restored for the view
9280     * hierarchy containing this view.
9281     * <p>
9282     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9283     * window or serves as a target of cluster navigation.
9284     *
9285     * @see #restoreDefaultFocus(int)
9286     *
9287     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
9288     * @attr ref android.R.styleable#View_focusedByDefault
9289     */
9290    @ViewDebug.ExportedProperty(category = "focusedByDefault")
9291    public final boolean isFocusedByDefault() {
9292        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
9293    }
9294
9295    /**
9296     * Sets whether this View should receive focus when the focus is restored for the view
9297     * hierarchy containing this view.
9298     * <p>
9299     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9300     * window or serves as a target of cluster navigation.
9301     *
9302     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
9303     *                           {@code false} otherwise.
9304     *
9305     * @see #restoreDefaultFocus(int)
9306     *
9307     * @attr ref android.R.styleable#View_focusedByDefault
9308     */
9309    public void setFocusedByDefault(boolean isFocusedByDefault) {
9310        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
9311            return;
9312        }
9313
9314        if (isFocusedByDefault) {
9315            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
9316        } else {
9317            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
9318        }
9319
9320        if (mParent instanceof ViewGroup) {
9321            if (isFocusedByDefault) {
9322                ((ViewGroup) mParent).setDefaultFocus(this);
9323            } else {
9324                ((ViewGroup) mParent).clearDefaultFocus(this);
9325            }
9326        }
9327    }
9328
9329    /**
9330     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
9331     *
9332     * @return {@code true} if this view has default focus, {@code false} otherwise
9333     */
9334    boolean hasDefaultFocus() {
9335        return isFocusedByDefault();
9336    }
9337
9338    /**
9339     * Find the nearest keyboard navigation cluster in the specified direction.
9340     * This does not actually give focus to that cluster.
9341     *
9342     * @param currentCluster The starting point of the search. Null means the current cluster is not
9343     *                       found yet
9344     * @param direction Direction to look
9345     *
9346     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
9347     *         can be found
9348     */
9349    public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
9350        if (isKeyboardNavigationCluster()) {
9351            currentCluster = this;
9352        }
9353        if (isRootNamespace()) {
9354            // Root namespace means we should consider ourselves the top of the
9355            // tree for group searching; otherwise we could be group searching
9356            // into other tabs.  see LocalActivityManager and TabHost for more info.
9357            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
9358                    this, currentCluster, direction);
9359        } else if (mParent != null) {
9360            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
9361        }
9362        return null;
9363    }
9364
9365    /**
9366     * This method is the last chance for the focused view and its ancestors to
9367     * respond to an arrow key. This is called when the focused view did not
9368     * consume the key internally, nor could the view system find a new view in
9369     * the requested direction to give focus to.
9370     *
9371     * @param focused The currently focused view.
9372     * @param direction The direction focus wants to move. One of FOCUS_UP,
9373     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
9374     * @return True if the this view consumed this unhandled move.
9375     */
9376    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
9377        return false;
9378    }
9379
9380    /**
9381     * If a user manually specified the next view id for a particular direction,
9382     * use the root to look up the view.
9383     * @param root The root view of the hierarchy containing this view.
9384     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
9385     * or FOCUS_BACKWARD.
9386     * @return The user specified next view, or null if there is none.
9387     */
9388    View findUserSetNextFocus(View root, @FocusDirection int direction) {
9389        switch (direction) {
9390            case FOCUS_LEFT:
9391                if (mNextFocusLeftId == View.NO_ID) return null;
9392                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
9393            case FOCUS_RIGHT:
9394                if (mNextFocusRightId == View.NO_ID) return null;
9395                return findViewInsideOutShouldExist(root, mNextFocusRightId);
9396            case FOCUS_UP:
9397                if (mNextFocusUpId == View.NO_ID) return null;
9398                return findViewInsideOutShouldExist(root, mNextFocusUpId);
9399            case FOCUS_DOWN:
9400                if (mNextFocusDownId == View.NO_ID) return null;
9401                return findViewInsideOutShouldExist(root, mNextFocusDownId);
9402            case FOCUS_FORWARD:
9403                if (mNextFocusForwardId == View.NO_ID) return null;
9404                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
9405            case FOCUS_BACKWARD: {
9406                if (mID == View.NO_ID) return null;
9407                final int id = mID;
9408                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
9409                    @Override
9410                    public boolean test(View t) {
9411                        return t.mNextFocusForwardId == id;
9412                    }
9413                });
9414            }
9415        }
9416        return null;
9417    }
9418
9419    private View findViewInsideOutShouldExist(View root, int id) {
9420        if (mMatchIdPredicate == null) {
9421            mMatchIdPredicate = new MatchIdPredicate();
9422        }
9423        mMatchIdPredicate.mId = id;
9424        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
9425        if (result == null) {
9426            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
9427        }
9428        return result;
9429    }
9430
9431    /**
9432     * Find and return all focusable views that are descendants of this view,
9433     * possibly including this view if it is focusable itself.
9434     *
9435     * @param direction The direction of the focus
9436     * @return A list of focusable views
9437     */
9438    public ArrayList<View> getFocusables(@FocusDirection int direction) {
9439        ArrayList<View> result = new ArrayList<View>(24);
9440        addFocusables(result, direction);
9441        return result;
9442    }
9443
9444    /**
9445     * Add any focusable views that are descendants of this view (possibly
9446     * including this view if it is focusable itself) to views.  If we are in touch mode,
9447     * only add views that are also focusable in touch mode.
9448     *
9449     * @param views Focusable views found so far
9450     * @param direction The direction of the focus
9451     */
9452    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
9453        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
9454    }
9455
9456    /**
9457     * Adds any focusable views that are descendants of this view (possibly
9458     * including this view if it is focusable itself) to views. This method
9459     * adds all focusable views regardless if we are in touch mode or
9460     * only views focusable in touch mode if we are in touch mode or
9461     * only views that can take accessibility focus if accessibility is enabled
9462     * depending on the focusable mode parameter.
9463     *
9464     * @param views Focusable views found so far or null if all we are interested is
9465     *        the number of focusables.
9466     * @param direction The direction of the focus.
9467     * @param focusableMode The type of focusables to be added.
9468     *
9469     * @see #FOCUSABLES_ALL
9470     * @see #FOCUSABLES_TOUCH_MODE
9471     */
9472    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
9473            @FocusableMode int focusableMode) {
9474        if (views == null) {
9475            return;
9476        }
9477        if (!isFocusable()) {
9478            return;
9479        }
9480        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
9481                && !isFocusableInTouchMode()) {
9482            return;
9483        }
9484        views.add(this);
9485    }
9486
9487    /**
9488     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
9489     * including this view if it is a cluster root itself) to views.
9490     *
9491     * @param views Keyboard navigation cluster roots found so far
9492     * @param direction Direction to look
9493     */
9494    public void addKeyboardNavigationClusters(
9495            @NonNull Collection<View> views,
9496            int direction) {
9497        if (!isKeyboardNavigationCluster()) {
9498            return;
9499        }
9500        if (!hasFocusable()) {
9501            return;
9502        }
9503        views.add(this);
9504    }
9505
9506    /**
9507     * Finds the Views that contain given text. The containment is case insensitive.
9508     * The search is performed by either the text that the View renders or the content
9509     * description that describes the view for accessibility purposes and the view does
9510     * not render or both. Clients can specify how the search is to be performed via
9511     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
9512     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
9513     *
9514     * @param outViews The output list of matching Views.
9515     * @param searched The text to match against.
9516     *
9517     * @see #FIND_VIEWS_WITH_TEXT
9518     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
9519     * @see #setContentDescription(CharSequence)
9520     */
9521    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
9522            @FindViewFlags int flags) {
9523        if (getAccessibilityNodeProvider() != null) {
9524            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
9525                outViews.add(this);
9526            }
9527        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
9528                && (searched != null && searched.length() > 0)
9529                && (mContentDescription != null && mContentDescription.length() > 0)) {
9530            String searchedLowerCase = searched.toString().toLowerCase();
9531            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
9532            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
9533                outViews.add(this);
9534            }
9535        }
9536    }
9537
9538    /**
9539     * Find and return all touchable views that are descendants of this view,
9540     * possibly including this view if it is touchable itself.
9541     *
9542     * @return A list of touchable views
9543     */
9544    public ArrayList<View> getTouchables() {
9545        ArrayList<View> result = new ArrayList<View>();
9546        addTouchables(result);
9547        return result;
9548    }
9549
9550    /**
9551     * Add any touchable views that are descendants of this view (possibly
9552     * including this view if it is touchable itself) to views.
9553     *
9554     * @param views Touchable views found so far
9555     */
9556    public void addTouchables(ArrayList<View> views) {
9557        final int viewFlags = mViewFlags;
9558
9559        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
9560                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
9561                && (viewFlags & ENABLED_MASK) == ENABLED) {
9562            views.add(this);
9563        }
9564    }
9565
9566    /**
9567     * Returns whether this View is accessibility focused.
9568     *
9569     * @return True if this View is accessibility focused.
9570     */
9571    public boolean isAccessibilityFocused() {
9572        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
9573    }
9574
9575    /**
9576     * Call this to try to give accessibility focus to this view.
9577     *
9578     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
9579     * returns false or the view is no visible or the view already has accessibility
9580     * focus.
9581     *
9582     * See also {@link #focusSearch(int)}, which is what you call to say that you
9583     * have focus, and you want your parent to look for the next one.
9584     *
9585     * @return Whether this view actually took accessibility focus.
9586     *
9587     * @hide
9588     */
9589    public boolean requestAccessibilityFocus() {
9590        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
9591        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
9592            return false;
9593        }
9594        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9595            return false;
9596        }
9597        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
9598            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
9599            ViewRootImpl viewRootImpl = getViewRootImpl();
9600            if (viewRootImpl != null) {
9601                viewRootImpl.setAccessibilityFocus(this, null);
9602            }
9603            invalidate();
9604            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
9605            return true;
9606        }
9607        return false;
9608    }
9609
9610    /**
9611     * Call this to try to clear accessibility focus of this view.
9612     *
9613     * See also {@link #focusSearch(int)}, which is what you call to say that you
9614     * have focus, and you want your parent to look for the next one.
9615     *
9616     * @hide
9617     */
9618    public void clearAccessibilityFocus() {
9619        clearAccessibilityFocusNoCallbacks(0);
9620
9621        // Clear the global reference of accessibility focus if this view or
9622        // any of its descendants had accessibility focus. This will NOT send
9623        // an event or update internal state if focus is cleared from a
9624        // descendant view, which may leave views in inconsistent states.
9625        final ViewRootImpl viewRootImpl = getViewRootImpl();
9626        if (viewRootImpl != null) {
9627            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
9628            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
9629                viewRootImpl.setAccessibilityFocus(null, null);
9630            }
9631        }
9632    }
9633
9634    private void sendAccessibilityHoverEvent(int eventType) {
9635        // Since we are not delivering to a client accessibility events from not
9636        // important views (unless the clinet request that) we need to fire the
9637        // event from the deepest view exposed to the client. As a consequence if
9638        // the user crosses a not exposed view the client will see enter and exit
9639        // of the exposed predecessor followed by and enter and exit of that same
9640        // predecessor when entering and exiting the not exposed descendant. This
9641        // is fine since the client has a clear idea which view is hovered at the
9642        // price of a couple more events being sent. This is a simple and
9643        // working solution.
9644        View source = this;
9645        while (true) {
9646            if (source.includeForAccessibility()) {
9647                source.sendAccessibilityEvent(eventType);
9648                return;
9649            }
9650            ViewParent parent = source.getParent();
9651            if (parent instanceof View) {
9652                source = (View) parent;
9653            } else {
9654                return;
9655            }
9656        }
9657    }
9658
9659    /**
9660     * Clears accessibility focus without calling any callback methods
9661     * normally invoked in {@link #clearAccessibilityFocus()}. This method
9662     * is used separately from that one for clearing accessibility focus when
9663     * giving this focus to another view.
9664     *
9665     * @param action The action, if any, that led to focus being cleared. Set to
9666     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
9667     * the window.
9668     */
9669    void clearAccessibilityFocusNoCallbacks(int action) {
9670        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
9671            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
9672            invalidate();
9673            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9674                AccessibilityEvent event = AccessibilityEvent.obtain(
9675                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
9676                event.setAction(action);
9677                if (mAccessibilityDelegate != null) {
9678                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
9679                } else {
9680                    sendAccessibilityEventUnchecked(event);
9681                }
9682            }
9683        }
9684    }
9685
9686    /**
9687     * Call this to try to give focus to a specific view or to one of its
9688     * descendants.
9689     *
9690     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9691     * false), or if it is focusable and it is not focusable in touch mode
9692     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9693     *
9694     * See also {@link #focusSearch(int)}, which is what you call to say that you
9695     * have focus, and you want your parent to look for the next one.
9696     *
9697     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
9698     * {@link #FOCUS_DOWN} and <code>null</code>.
9699     *
9700     * @return Whether this view or one of its descendants actually took focus.
9701     */
9702    public final boolean requestFocus() {
9703        return requestFocus(View.FOCUS_DOWN);
9704    }
9705
9706    /**
9707     * This will request focus for whichever View was last focused within this
9708     * cluster before a focus-jump out of it.
9709     *
9710     * @hide
9711     */
9712    @TestApi
9713    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
9714        // Prioritize focusableByDefault over algorithmic focus selection.
9715        if (restoreDefaultFocus()) {
9716            return true;
9717        }
9718        return requestFocus(direction);
9719    }
9720
9721    /**
9722     * This will request focus for whichever View not in a cluster was last focused before a
9723     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
9724     * the "first" focusable view it finds.
9725     *
9726     * @hide
9727     */
9728    @TestApi
9729    public boolean restoreFocusNotInCluster() {
9730        return requestFocus(View.FOCUS_DOWN);
9731    }
9732
9733    /**
9734     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
9735     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
9736     *
9737     * @return Whether this view or one of its descendants actually took focus
9738     */
9739    public boolean restoreDefaultFocus() {
9740        return requestFocus(View.FOCUS_DOWN);
9741    }
9742
9743    /**
9744     * Call this to try to give focus to a specific view or to one of its
9745     * descendants and give it a hint about what direction focus is heading.
9746     *
9747     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9748     * false), or if it is focusable and it is not focusable in touch mode
9749     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9750     *
9751     * See also {@link #focusSearch(int)}, which is what you call to say that you
9752     * have focus, and you want your parent to look for the next one.
9753     *
9754     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
9755     * <code>null</code> set for the previously focused rectangle.
9756     *
9757     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9758     * @return Whether this view or one of its descendants actually took focus.
9759     */
9760    public final boolean requestFocus(int direction) {
9761        return requestFocus(direction, null);
9762    }
9763
9764    /**
9765     * Call this to try to give focus to a specific view or to one of its descendants
9766     * and give it hints about the direction and a specific rectangle that the focus
9767     * is coming from.  The rectangle can help give larger views a finer grained hint
9768     * about where focus is coming from, and therefore, where to show selection, or
9769     * forward focus change internally.
9770     *
9771     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
9772     * false), or if it is focusable and it is not focusable in touch mode
9773     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
9774     *
9775     * A View will not take focus if it is not visible.
9776     *
9777     * A View will not take focus if one of its parents has
9778     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
9779     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
9780     *
9781     * See also {@link #focusSearch(int)}, which is what you call to say that you
9782     * have focus, and you want your parent to look for the next one.
9783     *
9784     * You may wish to override this method if your custom {@link View} has an internal
9785     * {@link View} that it wishes to forward the request to.
9786     *
9787     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9788     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
9789     *        to give a finer grained hint about where focus is coming from.  May be null
9790     *        if there is no hint.
9791     * @return Whether this view or one of its descendants actually took focus.
9792     */
9793    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
9794        return requestFocusNoSearch(direction, previouslyFocusedRect);
9795    }
9796
9797    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
9798        // need to be focusable
9799        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
9800                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9801            return false;
9802        }
9803
9804        // need to be focusable in touch mode if in touch mode
9805        if (isInTouchMode() &&
9806            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
9807               return false;
9808        }
9809
9810        // need to not have any parents blocking us
9811        if (hasAncestorThatBlocksDescendantFocus()) {
9812            return false;
9813        }
9814
9815        handleFocusGainInternal(direction, previouslyFocusedRect);
9816        return true;
9817    }
9818
9819    /**
9820     * Call this to try to give focus to a specific view or to one of its descendants. This is a
9821     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
9822     * touch mode to request focus when they are touched.
9823     *
9824     * @return Whether this view or one of its descendants actually took focus.
9825     *
9826     * @see #isInTouchMode()
9827     *
9828     */
9829    public final boolean requestFocusFromTouch() {
9830        // Leave touch mode if we need to
9831        if (isInTouchMode()) {
9832            ViewRootImpl viewRoot = getViewRootImpl();
9833            if (viewRoot != null) {
9834                viewRoot.ensureTouchMode(false);
9835            }
9836        }
9837        return requestFocus(View.FOCUS_DOWN);
9838    }
9839
9840    /**
9841     * @return Whether any ancestor of this view blocks descendant focus.
9842     */
9843    private boolean hasAncestorThatBlocksDescendantFocus() {
9844        final boolean focusableInTouchMode = isFocusableInTouchMode();
9845        ViewParent ancestor = mParent;
9846        while (ancestor instanceof ViewGroup) {
9847            final ViewGroup vgAncestor = (ViewGroup) ancestor;
9848            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
9849                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
9850                return true;
9851            } else {
9852                ancestor = vgAncestor.getParent();
9853            }
9854        }
9855        return false;
9856    }
9857
9858    /**
9859     * Gets the mode for determining whether this View is important for accessibility.
9860     * A view is important for accessibility if it fires accessibility events and if it
9861     * is reported to accessibility services that query the screen.
9862     *
9863     * @return The mode for determining whether a view is important for accessibility, one
9864     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
9865     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
9866     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
9867     *
9868     * @attr ref android.R.styleable#View_importantForAccessibility
9869     *
9870     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9871     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9872     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9873     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9874     */
9875    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
9876            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
9877            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
9878            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
9879            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
9880                    to = "noHideDescendants")
9881        })
9882    public int getImportantForAccessibility() {
9883        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
9884                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
9885    }
9886
9887    /**
9888     * Sets the live region mode for this view. This indicates to accessibility
9889     * services whether they should automatically notify the user about changes
9890     * to the view's content description or text, or to the content descriptions
9891     * or text of the view's children (where applicable).
9892     * <p>
9893     * For example, in a login screen with a TextView that displays an "incorrect
9894     * password" notification, that view should be marked as a live region with
9895     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9896     * <p>
9897     * To disable change notifications for this view, use
9898     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
9899     * mode for most views.
9900     * <p>
9901     * To indicate that the user should be notified of changes, use
9902     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
9903     * <p>
9904     * If the view's changes should interrupt ongoing speech and notify the user
9905     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
9906     *
9907     * @param mode The live region mode for this view, one of:
9908     *        <ul>
9909     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
9910     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
9911     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
9912     *        </ul>
9913     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9914     */
9915    public void setAccessibilityLiveRegion(int mode) {
9916        if (mode != getAccessibilityLiveRegion()) {
9917            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9918            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
9919                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
9920            notifyViewAccessibilityStateChangedIfNeeded(
9921                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9922        }
9923    }
9924
9925    /**
9926     * Gets the live region mode for this View.
9927     *
9928     * @return The live region mode for the view.
9929     *
9930     * @attr ref android.R.styleable#View_accessibilityLiveRegion
9931     *
9932     * @see #setAccessibilityLiveRegion(int)
9933     */
9934    public int getAccessibilityLiveRegion() {
9935        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
9936                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
9937    }
9938
9939    /**
9940     * Sets how to determine whether this view is important for accessibility
9941     * which is if it fires accessibility events and if it is reported to
9942     * accessibility services that query the screen.
9943     *
9944     * @param mode How to determine whether this view is important for accessibility.
9945     *
9946     * @attr ref android.R.styleable#View_importantForAccessibility
9947     *
9948     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
9949     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
9950     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
9951     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
9952     */
9953    public void setImportantForAccessibility(int mode) {
9954        final int oldMode = getImportantForAccessibility();
9955        if (mode != oldMode) {
9956            final boolean hideDescendants =
9957                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
9958
9959            // If this node or its descendants are no longer important, try to
9960            // clear accessibility focus.
9961            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
9962                final View focusHost = findAccessibilityFocusHost(hideDescendants);
9963                if (focusHost != null) {
9964                    focusHost.clearAccessibilityFocus();
9965                }
9966            }
9967
9968            // If we're moving between AUTO and another state, we might not need
9969            // to send a subtree changed notification. We'll store the computed
9970            // importance, since we'll need to check it later to make sure.
9971            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
9972                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
9973            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
9974            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9975            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
9976                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
9977            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
9978                notifySubtreeAccessibilityStateChangedIfNeeded();
9979            } else {
9980                notifyViewAccessibilityStateChangedIfNeeded(
9981                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9982            }
9983        }
9984    }
9985
9986    /**
9987     * Returns the view within this view's hierarchy that is hosting
9988     * accessibility focus.
9989     *
9990     * @param searchDescendants whether to search for focus in descendant views
9991     * @return the view hosting accessibility focus, or {@code null}
9992     */
9993    private View findAccessibilityFocusHost(boolean searchDescendants) {
9994        if (isAccessibilityFocusedViewOrHost()) {
9995            return this;
9996        }
9997
9998        if (searchDescendants) {
9999            final ViewRootImpl viewRoot = getViewRootImpl();
10000            if (viewRoot != null) {
10001                final View focusHost = viewRoot.getAccessibilityFocusedHost();
10002                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10003                    return focusHost;
10004                }
10005            }
10006        }
10007
10008        return null;
10009    }
10010
10011    /**
10012     * Computes whether this view should be exposed for accessibility. In
10013     * general, views that are interactive or provide information are exposed
10014     * while views that serve only as containers are hidden.
10015     * <p>
10016     * If an ancestor of this view has importance
10017     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
10018     * returns <code>false</code>.
10019     * <p>
10020     * Otherwise, the value is computed according to the view's
10021     * {@link #getImportantForAccessibility()} value:
10022     * <ol>
10023     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
10024     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
10025     * </code>
10026     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
10027     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
10028     * view satisfies any of the following:
10029     * <ul>
10030     * <li>Is actionable, e.g. {@link #isClickable()},
10031     * {@link #isLongClickable()}, or {@link #isFocusable()}
10032     * <li>Has an {@link AccessibilityDelegate}
10033     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
10034     * {@link OnKeyListener}, etc.
10035     * <li>Is an accessibility live region, e.g.
10036     * {@link #getAccessibilityLiveRegion()} is not
10037     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
10038     * </ul>
10039     * </ol>
10040     *
10041     * @return Whether the view is exposed for accessibility.
10042     * @see #setImportantForAccessibility(int)
10043     * @see #getImportantForAccessibility()
10044     */
10045    public boolean isImportantForAccessibility() {
10046        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10047                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10048        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
10049                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10050            return false;
10051        }
10052
10053        // Check parent mode to ensure we're not hidden.
10054        ViewParent parent = mParent;
10055        while (parent instanceof View) {
10056            if (((View) parent).getImportantForAccessibility()
10057                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10058                return false;
10059            }
10060            parent = parent.getParent();
10061        }
10062
10063        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
10064                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
10065                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
10066    }
10067
10068    /**
10069     * Gets the parent for accessibility purposes. Note that the parent for
10070     * accessibility is not necessary the immediate parent. It is the first
10071     * predecessor that is important for accessibility.
10072     *
10073     * @return The parent for accessibility purposes.
10074     */
10075    public ViewParent getParentForAccessibility() {
10076        if (mParent instanceof View) {
10077            View parentView = (View) mParent;
10078            if (parentView.includeForAccessibility()) {
10079                return mParent;
10080            } else {
10081                return mParent.getParentForAccessibility();
10082            }
10083        }
10084        return null;
10085    }
10086
10087    /**
10088     * Adds the children of this View relevant for accessibility to the given list
10089     * as output. Since some Views are not important for accessibility the added
10090     * child views are not necessarily direct children of this view, rather they are
10091     * the first level of descendants important for accessibility.
10092     *
10093     * @param outChildren The output list that will receive children for accessibility.
10094     */
10095    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
10096
10097    }
10098
10099    /**
10100     * Whether to regard this view for accessibility. A view is regarded for
10101     * accessibility if it is important for accessibility or the querying
10102     * accessibility service has explicitly requested that view not
10103     * important for accessibility are regarded.
10104     *
10105     * @return Whether to regard the view for accessibility.
10106     *
10107     * @hide
10108     */
10109    public boolean includeForAccessibility() {
10110        if (mAttachInfo != null) {
10111            return (mAttachInfo.mAccessibilityFetchFlags
10112                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
10113                    || isImportantForAccessibility();
10114        }
10115        return false;
10116    }
10117
10118    /**
10119     * Returns whether the View is considered actionable from
10120     * accessibility perspective. Such view are important for
10121     * accessibility.
10122     *
10123     * @return True if the view is actionable for accessibility.
10124     *
10125     * @hide
10126     */
10127    public boolean isActionableForAccessibility() {
10128        return (isClickable() || isLongClickable() || isFocusable());
10129    }
10130
10131    /**
10132     * Returns whether the View has registered callbacks which makes it
10133     * important for accessibility.
10134     *
10135     * @return True if the view is actionable for accessibility.
10136     */
10137    private boolean hasListenersForAccessibility() {
10138        ListenerInfo info = getListenerInfo();
10139        return mTouchDelegate != null || info.mOnKeyListener != null
10140                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
10141                || info.mOnHoverListener != null || info.mOnDragListener != null;
10142    }
10143
10144    /**
10145     * Notifies that the accessibility state of this view changed. The change
10146     * is local to this view and does not represent structural changes such
10147     * as children and parent. For example, the view became focusable. The
10148     * notification is at at most once every
10149     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10150     * to avoid unnecessary load to the system. Also once a view has a pending
10151     * notification this method is a NOP until the notification has been sent.
10152     *
10153     * @hide
10154     */
10155    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
10156        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10157            return;
10158        }
10159        if (mSendViewStateChangedAccessibilityEvent == null) {
10160            mSendViewStateChangedAccessibilityEvent =
10161                    new SendViewStateChangedAccessibilityEvent();
10162        }
10163        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
10164    }
10165
10166    /**
10167     * Notifies that the accessibility state of this view changed. The change
10168     * is *not* local to this view and does represent structural changes such
10169     * as children and parent. For example, the view size changed. The
10170     * notification is at at most once every
10171     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10172     * to avoid unnecessary load to the system. Also once a view has a pending
10173     * notification this method is a NOP until the notification has been sent.
10174     *
10175     * @hide
10176     */
10177    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
10178        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10179            return;
10180        }
10181        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
10182            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10183            if (mParent != null) {
10184                try {
10185                    mParent.notifySubtreeAccessibilityStateChanged(
10186                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
10187                } catch (AbstractMethodError e) {
10188                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
10189                            " does not fully implement ViewParent", e);
10190                }
10191            }
10192        }
10193    }
10194
10195    /**
10196     * Change the visibility of the View without triggering any other changes. This is
10197     * important for transitions, where visibility changes should not adjust focus or
10198     * trigger a new layout. This is only used when the visibility has already been changed
10199     * and we need a transient value during an animation. When the animation completes,
10200     * the original visibility value is always restored.
10201     *
10202     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
10203     * @hide
10204     */
10205    public void setTransitionVisibility(@Visibility int visibility) {
10206        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
10207    }
10208
10209    /**
10210     * Reset the flag indicating the accessibility state of the subtree rooted
10211     * at this view changed.
10212     */
10213    void resetSubtreeAccessibilityStateChanged() {
10214        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10215    }
10216
10217    /**
10218     * Report an accessibility action to this view's parents for delegated processing.
10219     *
10220     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
10221     * call this method to delegate an accessibility action to a supporting parent. If the parent
10222     * returns true from its
10223     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
10224     * method this method will return true to signify that the action was consumed.</p>
10225     *
10226     * <p>This method is useful for implementing nested scrolling child views. If
10227     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
10228     * a custom view implementation may invoke this method to allow a parent to consume the
10229     * scroll first. If this method returns true the custom view should skip its own scrolling
10230     * behavior.</p>
10231     *
10232     * @param action Accessibility action to delegate
10233     * @param arguments Optional action arguments
10234     * @return true if the action was consumed by a parent
10235     */
10236    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
10237        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
10238            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
10239                return true;
10240            }
10241        }
10242        return false;
10243    }
10244
10245    /**
10246     * Performs the specified accessibility action on the view. For
10247     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
10248     * <p>
10249     * If an {@link AccessibilityDelegate} has been specified via calling
10250     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10251     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
10252     * is responsible for handling this call.
10253     * </p>
10254     *
10255     * <p>The default implementation will delegate
10256     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
10257     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
10258     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
10259     *
10260     * @param action The action to perform.
10261     * @param arguments Optional action arguments.
10262     * @return Whether the action was performed.
10263     */
10264    public boolean performAccessibilityAction(int action, Bundle arguments) {
10265      if (mAccessibilityDelegate != null) {
10266          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
10267      } else {
10268          return performAccessibilityActionInternal(action, arguments);
10269      }
10270    }
10271
10272   /**
10273    * @see #performAccessibilityAction(int, Bundle)
10274    *
10275    * Note: Called from the default {@link AccessibilityDelegate}.
10276    *
10277    * @hide
10278    */
10279    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
10280        if (isNestedScrollingEnabled()
10281                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
10282                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
10283                || action == R.id.accessibilityActionScrollUp
10284                || action == R.id.accessibilityActionScrollLeft
10285                || action == R.id.accessibilityActionScrollDown
10286                || action == R.id.accessibilityActionScrollRight)) {
10287            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
10288                return true;
10289            }
10290        }
10291
10292        switch (action) {
10293            case AccessibilityNodeInfo.ACTION_CLICK: {
10294                if (isClickable()) {
10295                    performClick();
10296                    return true;
10297                }
10298            } break;
10299            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
10300                if (isLongClickable()) {
10301                    performLongClick();
10302                    return true;
10303                }
10304            } break;
10305            case AccessibilityNodeInfo.ACTION_FOCUS: {
10306                if (!hasFocus()) {
10307                    // Get out of touch mode since accessibility
10308                    // wants to move focus around.
10309                    getViewRootImpl().ensureTouchMode(false);
10310                    return requestFocus();
10311                }
10312            } break;
10313            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
10314                if (hasFocus()) {
10315                    clearFocus();
10316                    return !isFocused();
10317                }
10318            } break;
10319            case AccessibilityNodeInfo.ACTION_SELECT: {
10320                if (!isSelected()) {
10321                    setSelected(true);
10322                    return isSelected();
10323                }
10324            } break;
10325            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
10326                if (isSelected()) {
10327                    setSelected(false);
10328                    return !isSelected();
10329                }
10330            } break;
10331            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
10332                if (!isAccessibilityFocused()) {
10333                    return requestAccessibilityFocus();
10334                }
10335            } break;
10336            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
10337                if (isAccessibilityFocused()) {
10338                    clearAccessibilityFocus();
10339                    return true;
10340                }
10341            } break;
10342            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
10343                if (arguments != null) {
10344                    final int granularity = arguments.getInt(
10345                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10346                    final boolean extendSelection = arguments.getBoolean(
10347                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10348                    return traverseAtGranularity(granularity, true, extendSelection);
10349                }
10350            } break;
10351            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
10352                if (arguments != null) {
10353                    final int granularity = arguments.getInt(
10354                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10355                    final boolean extendSelection = arguments.getBoolean(
10356                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10357                    return traverseAtGranularity(granularity, false, extendSelection);
10358                }
10359            } break;
10360            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
10361                CharSequence text = getIterableTextForAccessibility();
10362                if (text == null) {
10363                    return false;
10364                }
10365                final int start = (arguments != null) ? arguments.getInt(
10366                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
10367                final int end = (arguments != null) ? arguments.getInt(
10368                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
10369                // Only cursor position can be specified (selection length == 0)
10370                if ((getAccessibilitySelectionStart() != start
10371                        || getAccessibilitySelectionEnd() != end)
10372                        && (start == end)) {
10373                    setAccessibilitySelection(start, end);
10374                    notifyViewAccessibilityStateChangedIfNeeded(
10375                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10376                    return true;
10377                }
10378            } break;
10379            case R.id.accessibilityActionShowOnScreen: {
10380                if (mAttachInfo != null) {
10381                    final Rect r = mAttachInfo.mTmpInvalRect;
10382                    getDrawingRect(r);
10383                    return requestRectangleOnScreen(r, true);
10384                }
10385            } break;
10386            case R.id.accessibilityActionContextClick: {
10387                if (isContextClickable()) {
10388                    performContextClick();
10389                    return true;
10390                }
10391            } break;
10392        }
10393        return false;
10394    }
10395
10396    private boolean traverseAtGranularity(int granularity, boolean forward,
10397            boolean extendSelection) {
10398        CharSequence text = getIterableTextForAccessibility();
10399        if (text == null || text.length() == 0) {
10400            return false;
10401        }
10402        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
10403        if (iterator == null) {
10404            return false;
10405        }
10406        int current = getAccessibilitySelectionEnd();
10407        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10408            current = forward ? 0 : text.length();
10409        }
10410        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
10411        if (range == null) {
10412            return false;
10413        }
10414        final int segmentStart = range[0];
10415        final int segmentEnd = range[1];
10416        int selectionStart;
10417        int selectionEnd;
10418        if (extendSelection && isAccessibilitySelectionExtendable()) {
10419            selectionStart = getAccessibilitySelectionStart();
10420            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
10421                selectionStart = forward ? segmentStart : segmentEnd;
10422            }
10423            selectionEnd = forward ? segmentEnd : segmentStart;
10424        } else {
10425            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
10426        }
10427        setAccessibilitySelection(selectionStart, selectionEnd);
10428        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
10429                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
10430        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
10431        return true;
10432    }
10433
10434    /**
10435     * Gets the text reported for accessibility purposes.
10436     *
10437     * @return The accessibility text.
10438     *
10439     * @hide
10440     */
10441    public CharSequence getIterableTextForAccessibility() {
10442        return getContentDescription();
10443    }
10444
10445    /**
10446     * Gets whether accessibility selection can be extended.
10447     *
10448     * @return If selection is extensible.
10449     *
10450     * @hide
10451     */
10452    public boolean isAccessibilitySelectionExtendable() {
10453        return false;
10454    }
10455
10456    /**
10457     * @hide
10458     */
10459    public int getAccessibilitySelectionStart() {
10460        return mAccessibilityCursorPosition;
10461    }
10462
10463    /**
10464     * @hide
10465     */
10466    public int getAccessibilitySelectionEnd() {
10467        return getAccessibilitySelectionStart();
10468    }
10469
10470    /**
10471     * @hide
10472     */
10473    public void setAccessibilitySelection(int start, int end) {
10474        if (start ==  end && end == mAccessibilityCursorPosition) {
10475            return;
10476        }
10477        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
10478            mAccessibilityCursorPosition = start;
10479        } else {
10480            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
10481        }
10482        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
10483    }
10484
10485    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
10486            int fromIndex, int toIndex) {
10487        if (mParent == null) {
10488            return;
10489        }
10490        AccessibilityEvent event = AccessibilityEvent.obtain(
10491                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
10492        onInitializeAccessibilityEvent(event);
10493        onPopulateAccessibilityEvent(event);
10494        event.setFromIndex(fromIndex);
10495        event.setToIndex(toIndex);
10496        event.setAction(action);
10497        event.setMovementGranularity(granularity);
10498        mParent.requestSendAccessibilityEvent(this, event);
10499    }
10500
10501    /**
10502     * @hide
10503     */
10504    public TextSegmentIterator getIteratorForGranularity(int granularity) {
10505        switch (granularity) {
10506            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
10507                CharSequence text = getIterableTextForAccessibility();
10508                if (text != null && text.length() > 0) {
10509                    CharacterTextSegmentIterator iterator =
10510                        CharacterTextSegmentIterator.getInstance(
10511                                mContext.getResources().getConfiguration().locale);
10512                    iterator.initialize(text.toString());
10513                    return iterator;
10514                }
10515            } break;
10516            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
10517                CharSequence text = getIterableTextForAccessibility();
10518                if (text != null && text.length() > 0) {
10519                    WordTextSegmentIterator iterator =
10520                        WordTextSegmentIterator.getInstance(
10521                                mContext.getResources().getConfiguration().locale);
10522                    iterator.initialize(text.toString());
10523                    return iterator;
10524                }
10525            } break;
10526            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
10527                CharSequence text = getIterableTextForAccessibility();
10528                if (text != null && text.length() > 0) {
10529                    ParagraphTextSegmentIterator iterator =
10530                        ParagraphTextSegmentIterator.getInstance();
10531                    iterator.initialize(text.toString());
10532                    return iterator;
10533                }
10534            } break;
10535        }
10536        return null;
10537    }
10538
10539    /**
10540     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
10541     * and {@link #onFinishTemporaryDetach()}.
10542     *
10543     * <p>This method always returns {@code true} when called directly or indirectly from
10544     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
10545     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
10546     * <ul>
10547     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
10548     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
10549     * </ul>
10550     * </p>
10551     *
10552     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
10553     * and {@link #onFinishTemporaryDetach()}.
10554     */
10555    public final boolean isTemporarilyDetached() {
10556        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
10557    }
10558
10559    /**
10560     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
10561     * a container View.
10562     */
10563    @CallSuper
10564    public void dispatchStartTemporaryDetach() {
10565        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
10566        onStartTemporaryDetach();
10567    }
10568
10569    /**
10570     * This is called when a container is going to temporarily detach a child, with
10571     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
10572     * It will either be followed by {@link #onFinishTemporaryDetach()} or
10573     * {@link #onDetachedFromWindow()} when the container is done.
10574     */
10575    public void onStartTemporaryDetach() {
10576        removeUnsetPressCallback();
10577        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
10578    }
10579
10580    /**
10581     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
10582     * a container View.
10583     */
10584    @CallSuper
10585    public void dispatchFinishTemporaryDetach() {
10586        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
10587        onFinishTemporaryDetach();
10588        if (hasWindowFocus() && hasFocus()) {
10589            InputMethodManager.getInstance().focusIn(this);
10590        }
10591    }
10592
10593    /**
10594     * Called after {@link #onStartTemporaryDetach} when the container is done
10595     * changing the view.
10596     */
10597    public void onFinishTemporaryDetach() {
10598    }
10599
10600    /**
10601     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
10602     * for this view's window.  Returns null if the view is not currently attached
10603     * to the window.  Normally you will not need to use this directly, but
10604     * just use the standard high-level event callbacks like
10605     * {@link #onKeyDown(int, KeyEvent)}.
10606     */
10607    public KeyEvent.DispatcherState getKeyDispatcherState() {
10608        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
10609    }
10610
10611    /**
10612     * Dispatch a key event before it is processed by any input method
10613     * associated with the view hierarchy.  This can be used to intercept
10614     * key events in special situations before the IME consumes them; a
10615     * typical example would be handling the BACK key to update the application's
10616     * UI instead of allowing the IME to see it and close itself.
10617     *
10618     * @param event The key event to be dispatched.
10619     * @return True if the event was handled, false otherwise.
10620     */
10621    public boolean dispatchKeyEventPreIme(KeyEvent event) {
10622        return onKeyPreIme(event.getKeyCode(), event);
10623    }
10624
10625    /**
10626     * Dispatch a key event to the next view on the focus path. This path runs
10627     * from the top of the view tree down to the currently focused view. If this
10628     * view has focus, it will dispatch to itself. Otherwise it will dispatch
10629     * the next node down the focus path. This method also fires any key
10630     * listeners.
10631     *
10632     * @param event The key event to be dispatched.
10633     * @return True if the event was handled, false otherwise.
10634     */
10635    public boolean dispatchKeyEvent(KeyEvent event) {
10636        if (mInputEventConsistencyVerifier != null) {
10637            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
10638        }
10639
10640        // Give any attached key listener a first crack at the event.
10641        //noinspection SimplifiableIfStatement
10642        ListenerInfo li = mListenerInfo;
10643        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
10644                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
10645            return true;
10646        }
10647
10648        if (event.dispatch(this, mAttachInfo != null
10649                ? mAttachInfo.mKeyDispatchState : null, this)) {
10650            return true;
10651        }
10652
10653        if (mInputEventConsistencyVerifier != null) {
10654            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10655        }
10656        return false;
10657    }
10658
10659    /**
10660     * Dispatches a key shortcut event.
10661     *
10662     * @param event The key event to be dispatched.
10663     * @return True if the event was handled by the view, false otherwise.
10664     */
10665    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
10666        return onKeyShortcut(event.getKeyCode(), event);
10667    }
10668
10669    /**
10670     * Pass the touch screen motion event down to the target view, or this
10671     * view if it is the target.
10672     *
10673     * @param event The motion event to be dispatched.
10674     * @return True if the event was handled by the view, false otherwise.
10675     */
10676    public boolean dispatchTouchEvent(MotionEvent event) {
10677        // If the event should be handled by accessibility focus first.
10678        if (event.isTargetAccessibilityFocus()) {
10679            // We don't have focus or no virtual descendant has it, do not handle the event.
10680            if (!isAccessibilityFocusedViewOrHost()) {
10681                return false;
10682            }
10683            // We have focus and got the event, then use normal event dispatch.
10684            event.setTargetAccessibilityFocus(false);
10685        }
10686
10687        boolean result = false;
10688
10689        if (mInputEventConsistencyVerifier != null) {
10690            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
10691        }
10692
10693        final int actionMasked = event.getActionMasked();
10694        if (actionMasked == MotionEvent.ACTION_DOWN) {
10695            // Defensive cleanup for new gesture
10696            stopNestedScroll();
10697        }
10698
10699        if (onFilterTouchEventForSecurity(event)) {
10700            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
10701                result = true;
10702            }
10703            //noinspection SimplifiableIfStatement
10704            ListenerInfo li = mListenerInfo;
10705            if (li != null && li.mOnTouchListener != null
10706                    && (mViewFlags & ENABLED_MASK) == ENABLED
10707                    && li.mOnTouchListener.onTouch(this, event)) {
10708                result = true;
10709            }
10710
10711            if (!result && onTouchEvent(event)) {
10712                result = true;
10713            }
10714        }
10715
10716        if (!result && mInputEventConsistencyVerifier != null) {
10717            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10718        }
10719
10720        // Clean up after nested scrolls if this is the end of a gesture;
10721        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
10722        // of the gesture.
10723        if (actionMasked == MotionEvent.ACTION_UP ||
10724                actionMasked == MotionEvent.ACTION_CANCEL ||
10725                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
10726            stopNestedScroll();
10727        }
10728
10729        return result;
10730    }
10731
10732    boolean isAccessibilityFocusedViewOrHost() {
10733        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
10734                .getAccessibilityFocusedHost() == this);
10735    }
10736
10737    /**
10738     * Filter the touch event to apply security policies.
10739     *
10740     * @param event The motion event to be filtered.
10741     * @return True if the event should be dispatched, false if the event should be dropped.
10742     *
10743     * @see #getFilterTouchesWhenObscured
10744     */
10745    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
10746        //noinspection RedundantIfStatement
10747        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
10748                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
10749            // Window is obscured, drop this touch.
10750            return false;
10751        }
10752        return true;
10753    }
10754
10755    /**
10756     * Pass a trackball motion event down to the focused view.
10757     *
10758     * @param event The motion event to be dispatched.
10759     * @return True if the event was handled by the view, false otherwise.
10760     */
10761    public boolean dispatchTrackballEvent(MotionEvent event) {
10762        if (mInputEventConsistencyVerifier != null) {
10763            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
10764        }
10765
10766        return onTrackballEvent(event);
10767    }
10768
10769    /**
10770     * Pass a captured pointer event down to the focused view.
10771     *
10772     * @param event The motion event to be dispatched.
10773     * @return True if the event was handled by the view, false otherwise.
10774     */
10775    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
10776        if (!hasPointerCapture()) {
10777            return false;
10778        }
10779        //noinspection SimplifiableIfStatement
10780        ListenerInfo li = mListenerInfo;
10781        if (li != null && li.mOnCapturedPointerListener != null
10782                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
10783            return true;
10784        }
10785        return onCapturedPointerEvent(event);
10786    }
10787
10788    /**
10789     * Dispatch a generic motion event.
10790     * <p>
10791     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10792     * are delivered to the view under the pointer.  All other generic motion events are
10793     * delivered to the focused view.  Hover events are handled specially and are delivered
10794     * to {@link #onHoverEvent(MotionEvent)}.
10795     * </p>
10796     *
10797     * @param event The motion event to be dispatched.
10798     * @return True if the event was handled by the view, false otherwise.
10799     */
10800    public boolean dispatchGenericMotionEvent(MotionEvent event) {
10801        if (mInputEventConsistencyVerifier != null) {
10802            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
10803        }
10804
10805        final int source = event.getSource();
10806        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
10807            final int action = event.getAction();
10808            if (action == MotionEvent.ACTION_HOVER_ENTER
10809                    || action == MotionEvent.ACTION_HOVER_MOVE
10810                    || action == MotionEvent.ACTION_HOVER_EXIT) {
10811                if (dispatchHoverEvent(event)) {
10812                    return true;
10813                }
10814            } else if (dispatchGenericPointerEvent(event)) {
10815                return true;
10816            }
10817        } else if (dispatchGenericFocusedEvent(event)) {
10818            return true;
10819        }
10820
10821        if (dispatchGenericMotionEventInternal(event)) {
10822            return true;
10823        }
10824
10825        if (mInputEventConsistencyVerifier != null) {
10826            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10827        }
10828        return false;
10829    }
10830
10831    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
10832        //noinspection SimplifiableIfStatement
10833        ListenerInfo li = mListenerInfo;
10834        if (li != null && li.mOnGenericMotionListener != null
10835                && (mViewFlags & ENABLED_MASK) == ENABLED
10836                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
10837            return true;
10838        }
10839
10840        if (onGenericMotionEvent(event)) {
10841            return true;
10842        }
10843
10844        final int actionButton = event.getActionButton();
10845        switch (event.getActionMasked()) {
10846            case MotionEvent.ACTION_BUTTON_PRESS:
10847                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
10848                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10849                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10850                    if (performContextClick(event.getX(), event.getY())) {
10851                        mInContextButtonPress = true;
10852                        setPressed(true, event.getX(), event.getY());
10853                        removeTapCallback();
10854                        removeLongPressCallback();
10855                        return true;
10856                    }
10857                }
10858                break;
10859
10860            case MotionEvent.ACTION_BUTTON_RELEASE:
10861                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
10862                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
10863                    mInContextButtonPress = false;
10864                    mIgnoreNextUpEvent = true;
10865                }
10866                break;
10867        }
10868
10869        if (mInputEventConsistencyVerifier != null) {
10870            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
10871        }
10872        return false;
10873    }
10874
10875    /**
10876     * Dispatch a hover event.
10877     * <p>
10878     * Do not call this method directly.
10879     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10880     * </p>
10881     *
10882     * @param event The motion event to be dispatched.
10883     * @return True if the event was handled by the view, false otherwise.
10884     */
10885    protected boolean dispatchHoverEvent(MotionEvent event) {
10886        ListenerInfo li = mListenerInfo;
10887        //noinspection SimplifiableIfStatement
10888        if (li != null && li.mOnHoverListener != null
10889                && (mViewFlags & ENABLED_MASK) == ENABLED
10890                && li.mOnHoverListener.onHover(this, event)) {
10891            return true;
10892        }
10893
10894        return onHoverEvent(event);
10895    }
10896
10897    /**
10898     * Returns true if the view has a child to which it has recently sent
10899     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
10900     * it does not have a hovered child, then it must be the innermost hovered view.
10901     * @hide
10902     */
10903    protected boolean hasHoveredChild() {
10904        return false;
10905    }
10906
10907    /**
10908     * Dispatch a generic motion event to the view under the first pointer.
10909     * <p>
10910     * Do not call this method directly.
10911     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10912     * </p>
10913     *
10914     * @param event The motion event to be dispatched.
10915     * @return True if the event was handled by the view, false otherwise.
10916     */
10917    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
10918        return false;
10919    }
10920
10921    /**
10922     * Dispatch a generic motion event to the currently focused view.
10923     * <p>
10924     * Do not call this method directly.
10925     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
10926     * </p>
10927     *
10928     * @param event The motion event to be dispatched.
10929     * @return True if the event was handled by the view, false otherwise.
10930     */
10931    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
10932        return false;
10933    }
10934
10935    /**
10936     * Dispatch a pointer event.
10937     * <p>
10938     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
10939     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
10940     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
10941     * and should not be expected to handle other pointing device features.
10942     * </p>
10943     *
10944     * @param event The motion event to be dispatched.
10945     * @return True if the event was handled by the view, false otherwise.
10946     * @hide
10947     */
10948    public final boolean dispatchPointerEvent(MotionEvent event) {
10949        if (event.isTouchEvent()) {
10950            return dispatchTouchEvent(event);
10951        } else {
10952            return dispatchGenericMotionEvent(event);
10953        }
10954    }
10955
10956    /**
10957     * Called when the window containing this view gains or loses window focus.
10958     * ViewGroups should override to route to their children.
10959     *
10960     * @param hasFocus True if the window containing this view now has focus,
10961     *        false otherwise.
10962     */
10963    public void dispatchWindowFocusChanged(boolean hasFocus) {
10964        onWindowFocusChanged(hasFocus);
10965    }
10966
10967    /**
10968     * Called when the window containing this view gains or loses focus.  Note
10969     * that this is separate from view focus: to receive key events, both
10970     * your view and its window must have focus.  If a window is displayed
10971     * on top of yours that takes input focus, then your own window will lose
10972     * focus but the view focus will remain unchanged.
10973     *
10974     * @param hasWindowFocus True if the window containing this view now has
10975     *        focus, false otherwise.
10976     */
10977    public void onWindowFocusChanged(boolean hasWindowFocus) {
10978        InputMethodManager imm = InputMethodManager.peekInstance();
10979        if (!hasWindowFocus) {
10980            if (isPressed()) {
10981                setPressed(false);
10982            }
10983            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
10984            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10985                imm.focusOut(this);
10986            }
10987            removeLongPressCallback();
10988            removeTapCallback();
10989            onFocusLost();
10990        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
10991            imm.focusIn(this);
10992        }
10993        refreshDrawableState();
10994    }
10995
10996    /**
10997     * Returns true if this view is in a window that currently has window focus.
10998     * Note that this is not the same as the view itself having focus.
10999     *
11000     * @return True if this view is in a window that currently has window focus.
11001     */
11002    public boolean hasWindowFocus() {
11003        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
11004    }
11005
11006    /**
11007     * Dispatch a view visibility change down the view hierarchy.
11008     * ViewGroups should override to route to their children.
11009     * @param changedView The view whose visibility changed. Could be 'this' or
11010     * an ancestor view.
11011     * @param visibility The new visibility of changedView: {@link #VISIBLE},
11012     * {@link #INVISIBLE} or {@link #GONE}.
11013     */
11014    protected void dispatchVisibilityChanged(@NonNull View changedView,
11015            @Visibility int visibility) {
11016        onVisibilityChanged(changedView, visibility);
11017    }
11018
11019    /**
11020     * Called when the visibility of the view or an ancestor of the view has
11021     * changed.
11022     *
11023     * @param changedView The view whose visibility changed. May be
11024     *                    {@code this} or an ancestor view.
11025     * @param visibility The new visibility, one of {@link #VISIBLE},
11026     *                   {@link #INVISIBLE} or {@link #GONE}.
11027     */
11028    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
11029    }
11030
11031    /**
11032     * Dispatch a hint about whether this view is displayed. For instance, when
11033     * a View moves out of the screen, it might receives a display hint indicating
11034     * the view is not displayed. Applications should not <em>rely</em> on this hint
11035     * as there is no guarantee that they will receive one.
11036     *
11037     * @param hint A hint about whether or not this view is displayed:
11038     * {@link #VISIBLE} or {@link #INVISIBLE}.
11039     */
11040    public void dispatchDisplayHint(@Visibility int hint) {
11041        onDisplayHint(hint);
11042    }
11043
11044    /**
11045     * Gives this view a hint about whether is displayed or not. For instance, when
11046     * a View moves out of the screen, it might receives a display hint indicating
11047     * the view is not displayed. Applications should not <em>rely</em> on this hint
11048     * as there is no guarantee that they will receive one.
11049     *
11050     * @param hint A hint about whether or not this view is displayed:
11051     * {@link #VISIBLE} or {@link #INVISIBLE}.
11052     */
11053    protected void onDisplayHint(@Visibility int hint) {
11054    }
11055
11056    /**
11057     * Dispatch a window visibility change down the view hierarchy.
11058     * ViewGroups should override to route to their children.
11059     *
11060     * @param visibility The new visibility of the window.
11061     *
11062     * @see #onWindowVisibilityChanged(int)
11063     */
11064    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
11065        onWindowVisibilityChanged(visibility);
11066    }
11067
11068    /**
11069     * Called when the window containing has change its visibility
11070     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
11071     * that this tells you whether or not your window is being made visible
11072     * to the window manager; this does <em>not</em> tell you whether or not
11073     * your window is obscured by other windows on the screen, even if it
11074     * is itself visible.
11075     *
11076     * @param visibility The new visibility of the window.
11077     */
11078    protected void onWindowVisibilityChanged(@Visibility int visibility) {
11079        if (visibility == VISIBLE) {
11080            initialAwakenScrollBars();
11081        }
11082    }
11083
11084    /**
11085     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
11086     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
11087     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
11088     *
11089     * @param isVisible true if this view's visibility to the user is uninterrupted by its
11090     *                  ancestors or by window visibility
11091     * @return true if this view is visible to the user, not counting clipping or overlapping
11092     */
11093    boolean dispatchVisibilityAggregated(boolean isVisible) {
11094        final boolean thisVisible = getVisibility() == VISIBLE;
11095        // If we're not visible but something is telling us we are, ignore it.
11096        if (thisVisible || !isVisible) {
11097            onVisibilityAggregated(isVisible);
11098        }
11099        return thisVisible && isVisible;
11100    }
11101
11102    /**
11103     * Called when the user-visibility of this View is potentially affected by a change
11104     * to this view itself, an ancestor view or the window this view is attached to.
11105     *
11106     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
11107     *                  and this view's window is also visible
11108     */
11109    @CallSuper
11110    public void onVisibilityAggregated(boolean isVisible) {
11111        if (isVisible && mAttachInfo != null) {
11112            initialAwakenScrollBars();
11113        }
11114
11115        final Drawable dr = mBackground;
11116        if (dr != null && isVisible != dr.isVisible()) {
11117            dr.setVisible(isVisible, false);
11118        }
11119        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
11120        if (fg != null && isVisible != fg.isVisible()) {
11121            fg.setVisible(isVisible, false);
11122        }
11123    }
11124
11125    /**
11126     * Returns the current visibility of the window this view is attached to
11127     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
11128     *
11129     * @return Returns the current visibility of the view's window.
11130     */
11131    @Visibility
11132    public int getWindowVisibility() {
11133        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
11134    }
11135
11136    /**
11137     * Retrieve the overall visible display size in which the window this view is
11138     * attached to has been positioned in.  This takes into account screen
11139     * decorations above the window, for both cases where the window itself
11140     * is being position inside of them or the window is being placed under
11141     * then and covered insets are used for the window to position its content
11142     * inside.  In effect, this tells you the available area where content can
11143     * be placed and remain visible to users.
11144     *
11145     * <p>This function requires an IPC back to the window manager to retrieve
11146     * the requested information, so should not be used in performance critical
11147     * code like drawing.
11148     *
11149     * @param outRect Filled in with the visible display frame.  If the view
11150     * is not attached to a window, this is simply the raw display size.
11151     */
11152    public void getWindowVisibleDisplayFrame(Rect outRect) {
11153        if (mAttachInfo != null) {
11154            try {
11155                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11156            } catch (RemoteException e) {
11157                return;
11158            }
11159            // XXX This is really broken, and probably all needs to be done
11160            // in the window manager, and we need to know more about whether
11161            // we want the area behind or in front of the IME.
11162            final Rect insets = mAttachInfo.mVisibleInsets;
11163            outRect.left += insets.left;
11164            outRect.top += insets.top;
11165            outRect.right -= insets.right;
11166            outRect.bottom -= insets.bottom;
11167            return;
11168        }
11169        // The view is not attached to a display so we don't have a context.
11170        // Make a best guess about the display size.
11171        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11172        d.getRectSize(outRect);
11173    }
11174
11175    /**
11176     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
11177     * is currently in without any insets.
11178     *
11179     * @hide
11180     */
11181    public void getWindowDisplayFrame(Rect outRect) {
11182        if (mAttachInfo != null) {
11183            try {
11184                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11185            } catch (RemoteException e) {
11186                return;
11187            }
11188            return;
11189        }
11190        // The view is not attached to a display so we don't have a context.
11191        // Make a best guess about the display size.
11192        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11193        d.getRectSize(outRect);
11194    }
11195
11196    /**
11197     * Dispatch a notification about a resource configuration change down
11198     * the view hierarchy.
11199     * ViewGroups should override to route to their children.
11200     *
11201     * @param newConfig The new resource configuration.
11202     *
11203     * @see #onConfigurationChanged(android.content.res.Configuration)
11204     */
11205    public void dispatchConfigurationChanged(Configuration newConfig) {
11206        onConfigurationChanged(newConfig);
11207    }
11208
11209    /**
11210     * Called when the current configuration of the resources being used
11211     * by the application have changed.  You can use this to decide when
11212     * to reload resources that can changed based on orientation and other
11213     * configuration characteristics.  You only need to use this if you are
11214     * not relying on the normal {@link android.app.Activity} mechanism of
11215     * recreating the activity instance upon a configuration change.
11216     *
11217     * @param newConfig The new resource configuration.
11218     */
11219    protected void onConfigurationChanged(Configuration newConfig) {
11220    }
11221
11222    /**
11223     * Private function to aggregate all per-view attributes in to the view
11224     * root.
11225     */
11226    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11227        performCollectViewAttributes(attachInfo, visibility);
11228    }
11229
11230    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11231        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
11232            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
11233                attachInfo.mKeepScreenOn = true;
11234            }
11235            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
11236            ListenerInfo li = mListenerInfo;
11237            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
11238                attachInfo.mHasSystemUiListeners = true;
11239            }
11240        }
11241    }
11242
11243    void needGlobalAttributesUpdate(boolean force) {
11244        final AttachInfo ai = mAttachInfo;
11245        if (ai != null && !ai.mRecomputeGlobalAttributes) {
11246            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
11247                    || ai.mHasSystemUiListeners) {
11248                ai.mRecomputeGlobalAttributes = true;
11249            }
11250        }
11251    }
11252
11253    /**
11254     * Returns whether the device is currently in touch mode.  Touch mode is entered
11255     * once the user begins interacting with the device by touch, and affects various
11256     * things like whether focus is always visible to the user.
11257     *
11258     * @return Whether the device is in touch mode.
11259     */
11260    @ViewDebug.ExportedProperty
11261    public boolean isInTouchMode() {
11262        if (mAttachInfo != null) {
11263            return mAttachInfo.mInTouchMode;
11264        } else {
11265            return ViewRootImpl.isInTouchMode();
11266        }
11267    }
11268
11269    /**
11270     * Returns the context the view is running in, through which it can
11271     * access the current theme, resources, etc.
11272     *
11273     * @return The view's Context.
11274     */
11275    @ViewDebug.CapturedViewProperty
11276    public final Context getContext() {
11277        return mContext;
11278    }
11279
11280    /**
11281     * Handle a key event before it is processed by any input method
11282     * associated with the view hierarchy.  This can be used to intercept
11283     * key events in special situations before the IME consumes them; a
11284     * typical example would be handling the BACK key to update the application's
11285     * UI instead of allowing the IME to see it and close itself.
11286     *
11287     * @param keyCode The value in event.getKeyCode().
11288     * @param event Description of the key event.
11289     * @return If you handled the event, return true. If you want to allow the
11290     *         event to be handled by the next receiver, return false.
11291     */
11292    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
11293        return false;
11294    }
11295
11296    /**
11297     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
11298     * KeyEvent.Callback.onKeyDown()}: perform press of the view
11299     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
11300     * is released, if the view is enabled and clickable.
11301     * <p>
11302     * Key presses in software keyboards will generally NOT trigger this
11303     * listener, although some may elect to do so in some situations. Do not
11304     * rely on this to catch software key presses.
11305     *
11306     * @param keyCode a key code that represents the button pressed, from
11307     *                {@link android.view.KeyEvent}
11308     * @param event the KeyEvent object that defines the button action
11309     */
11310    public boolean onKeyDown(int keyCode, KeyEvent event) {
11311        if (KeyEvent.isConfirmKey(keyCode)) {
11312            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11313                return true;
11314            }
11315
11316            if (event.getRepeatCount() == 0) {
11317                // Long clickable items don't necessarily have to be clickable.
11318                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
11319                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11320                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
11321                    // For the purposes of menu anchoring and drawable hotspots,
11322                    // key events are considered to be at the center of the view.
11323                    final float x = getWidth() / 2f;
11324                    final float y = getHeight() / 2f;
11325                    if (clickable) {
11326                        setPressed(true, x, y);
11327                    }
11328                    checkForLongClick(0, x, y);
11329                    return true;
11330                }
11331            }
11332        }
11333
11334        return false;
11335    }
11336
11337    /**
11338     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
11339     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
11340     * the event).
11341     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11342     * although some may elect to do so in some situations. Do not rely on this to
11343     * catch software key presses.
11344     */
11345    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
11346        return false;
11347    }
11348
11349    /**
11350     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
11351     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
11352     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
11353     * or {@link KeyEvent#KEYCODE_SPACE} is released.
11354     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11355     * although some may elect to do so in some situations. Do not rely on this to
11356     * catch software key presses.
11357     *
11358     * @param keyCode A key code that represents the button pressed, from
11359     *                {@link android.view.KeyEvent}.
11360     * @param event   The KeyEvent object that defines the button action.
11361     */
11362    public boolean onKeyUp(int keyCode, KeyEvent event) {
11363        if (KeyEvent.isConfirmKey(keyCode)) {
11364            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11365                return true;
11366            }
11367            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
11368                setPressed(false);
11369
11370                if (!mHasPerformedLongPress) {
11371                    // This is a tap, so remove the longpress check
11372                    removeLongPressCallback();
11373                    return performClick();
11374                }
11375            }
11376        }
11377        return false;
11378    }
11379
11380    /**
11381     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
11382     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
11383     * the event).
11384     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11385     * although some may elect to do so in some situations. Do not rely on this to
11386     * catch software key presses.
11387     *
11388     * @param keyCode     A key code that represents the button pressed, from
11389     *                    {@link android.view.KeyEvent}.
11390     * @param repeatCount The number of times the action was made.
11391     * @param event       The KeyEvent object that defines the button action.
11392     */
11393    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
11394        return false;
11395    }
11396
11397    /**
11398     * Called on the focused view when a key shortcut event is not handled.
11399     * Override this method to implement local key shortcuts for the View.
11400     * Key shortcuts can also be implemented by setting the
11401     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
11402     *
11403     * @param keyCode The value in event.getKeyCode().
11404     * @param event Description of the key event.
11405     * @return If you handled the event, return true. If you want to allow the
11406     *         event to be handled by the next receiver, return false.
11407     */
11408    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
11409        return false;
11410    }
11411
11412    /**
11413     * Check whether the called view is a text editor, in which case it
11414     * would make sense to automatically display a soft input window for
11415     * it.  Subclasses should override this if they implement
11416     * {@link #onCreateInputConnection(EditorInfo)} to return true if
11417     * a call on that method would return a non-null InputConnection, and
11418     * they are really a first-class editor that the user would normally
11419     * start typing on when the go into a window containing your view.
11420     *
11421     * <p>The default implementation always returns false.  This does
11422     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
11423     * will not be called or the user can not otherwise perform edits on your
11424     * view; it is just a hint to the system that this is not the primary
11425     * purpose of this view.
11426     *
11427     * @return Returns true if this view is a text editor, else false.
11428     */
11429    public boolean onCheckIsTextEditor() {
11430        return false;
11431    }
11432
11433    /**
11434     * Create a new InputConnection for an InputMethod to interact
11435     * with the view.  The default implementation returns null, since it doesn't
11436     * support input methods.  You can override this to implement such support.
11437     * This is only needed for views that take focus and text input.
11438     *
11439     * <p>When implementing this, you probably also want to implement
11440     * {@link #onCheckIsTextEditor()} to indicate you will return a
11441     * non-null InputConnection.</p>
11442     *
11443     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
11444     * object correctly and in its entirety, so that the connected IME can rely
11445     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
11446     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
11447     * must be filled in with the correct cursor position for IMEs to work correctly
11448     * with your application.</p>
11449     *
11450     * @param outAttrs Fill in with attribute information about the connection.
11451     */
11452    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
11453        return null;
11454    }
11455
11456    /**
11457     * Called by the {@link android.view.inputmethod.InputMethodManager}
11458     * when a view who is not the current
11459     * input connection target is trying to make a call on the manager.  The
11460     * default implementation returns false; you can override this to return
11461     * true for certain views if you are performing InputConnection proxying
11462     * to them.
11463     * @param view The View that is making the InputMethodManager call.
11464     * @return Return true to allow the call, false to reject.
11465     */
11466    public boolean checkInputConnectionProxy(View view) {
11467        return false;
11468    }
11469
11470    /**
11471     * Show the context menu for this view. It is not safe to hold on to the
11472     * menu after returning from this method.
11473     *
11474     * You should normally not overload this method. Overload
11475     * {@link #onCreateContextMenu(ContextMenu)} or define an
11476     * {@link OnCreateContextMenuListener} to add items to the context menu.
11477     *
11478     * @param menu The context menu to populate
11479     */
11480    public void createContextMenu(ContextMenu menu) {
11481        ContextMenuInfo menuInfo = getContextMenuInfo();
11482
11483        // Sets the current menu info so all items added to menu will have
11484        // my extra info set.
11485        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
11486
11487        onCreateContextMenu(menu);
11488        ListenerInfo li = mListenerInfo;
11489        if (li != null && li.mOnCreateContextMenuListener != null) {
11490            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
11491        }
11492
11493        // Clear the extra information so subsequent items that aren't mine don't
11494        // have my extra info.
11495        ((MenuBuilder)menu).setCurrentMenuInfo(null);
11496
11497        if (mParent != null) {
11498            mParent.createContextMenu(menu);
11499        }
11500    }
11501
11502    /**
11503     * Views should implement this if they have extra information to associate
11504     * with the context menu. The return result is supplied as a parameter to
11505     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
11506     * callback.
11507     *
11508     * @return Extra information about the item for which the context menu
11509     *         should be shown. This information will vary across different
11510     *         subclasses of View.
11511     */
11512    protected ContextMenuInfo getContextMenuInfo() {
11513        return null;
11514    }
11515
11516    /**
11517     * Views should implement this if the view itself is going to add items to
11518     * the context menu.
11519     *
11520     * @param menu the context menu to populate
11521     */
11522    protected void onCreateContextMenu(ContextMenu menu) {
11523    }
11524
11525    /**
11526     * Implement this method to handle trackball motion events.  The
11527     * <em>relative</em> movement of the trackball since the last event
11528     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
11529     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
11530     * that a movement of 1 corresponds to the user pressing one DPAD key (so
11531     * they will often be fractional values, representing the more fine-grained
11532     * movement information available from a trackball).
11533     *
11534     * @param event The motion event.
11535     * @return True if the event was handled, false otherwise.
11536     */
11537    public boolean onTrackballEvent(MotionEvent event) {
11538        return false;
11539    }
11540
11541    /**
11542     * Implement this method to handle generic motion events.
11543     * <p>
11544     * Generic motion events describe joystick movements, mouse hovers, track pad
11545     * touches, scroll wheel movements and other input events.  The
11546     * {@link MotionEvent#getSource() source} of the motion event specifies
11547     * the class of input that was received.  Implementations of this method
11548     * must examine the bits in the source before processing the event.
11549     * The following code example shows how this is done.
11550     * </p><p>
11551     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11552     * are delivered to the view under the pointer.  All other generic motion events are
11553     * delivered to the focused view.
11554     * </p>
11555     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
11556     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
11557     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
11558     *             // process the joystick movement...
11559     *             return true;
11560     *         }
11561     *     }
11562     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
11563     *         switch (event.getAction()) {
11564     *             case MotionEvent.ACTION_HOVER_MOVE:
11565     *                 // process the mouse hover movement...
11566     *                 return true;
11567     *             case MotionEvent.ACTION_SCROLL:
11568     *                 // process the scroll wheel movement...
11569     *                 return true;
11570     *         }
11571     *     }
11572     *     return super.onGenericMotionEvent(event);
11573     * }</pre>
11574     *
11575     * @param event The generic motion event being processed.
11576     * @return True if the event was handled, false otherwise.
11577     */
11578    public boolean onGenericMotionEvent(MotionEvent event) {
11579        return false;
11580    }
11581
11582    /**
11583     * Implement this method to handle hover events.
11584     * <p>
11585     * This method is called whenever a pointer is hovering into, over, or out of the
11586     * bounds of a view and the view is not currently being touched.
11587     * Hover events are represented as pointer events with action
11588     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
11589     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
11590     * </p>
11591     * <ul>
11592     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
11593     * when the pointer enters the bounds of the view.</li>
11594     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
11595     * when the pointer has already entered the bounds of the view and has moved.</li>
11596     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
11597     * when the pointer has exited the bounds of the view or when the pointer is
11598     * about to go down due to a button click, tap, or similar user action that
11599     * causes the view to be touched.</li>
11600     * </ul>
11601     * <p>
11602     * The view should implement this method to return true to indicate that it is
11603     * handling the hover event, such as by changing its drawable state.
11604     * </p><p>
11605     * The default implementation calls {@link #setHovered} to update the hovered state
11606     * of the view when a hover enter or hover exit event is received, if the view
11607     * is enabled and is clickable.  The default implementation also sends hover
11608     * accessibility events.
11609     * </p>
11610     *
11611     * @param event The motion event that describes the hover.
11612     * @return True if the view handled the hover event.
11613     *
11614     * @see #isHovered
11615     * @see #setHovered
11616     * @see #onHoverChanged
11617     */
11618    public boolean onHoverEvent(MotionEvent event) {
11619        // The root view may receive hover (or touch) events that are outside the bounds of
11620        // the window.  This code ensures that we only send accessibility events for
11621        // hovers that are actually within the bounds of the root view.
11622        final int action = event.getActionMasked();
11623        if (!mSendingHoverAccessibilityEvents) {
11624            if ((action == MotionEvent.ACTION_HOVER_ENTER
11625                    || action == MotionEvent.ACTION_HOVER_MOVE)
11626                    && !hasHoveredChild()
11627                    && pointInView(event.getX(), event.getY())) {
11628                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
11629                mSendingHoverAccessibilityEvents = true;
11630            }
11631        } else {
11632            if (action == MotionEvent.ACTION_HOVER_EXIT
11633                    || (action == MotionEvent.ACTION_MOVE
11634                            && !pointInView(event.getX(), event.getY()))) {
11635                mSendingHoverAccessibilityEvents = false;
11636                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
11637            }
11638        }
11639
11640        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
11641                && event.isFromSource(InputDevice.SOURCE_MOUSE)
11642                && isOnScrollbar(event.getX(), event.getY())) {
11643            awakenScrollBars();
11644        }
11645        if (isHoverable()) {
11646            switch (action) {
11647                case MotionEvent.ACTION_HOVER_ENTER:
11648                    setHovered(true);
11649                    break;
11650                case MotionEvent.ACTION_HOVER_EXIT:
11651                    setHovered(false);
11652                    break;
11653            }
11654
11655            // Dispatch the event to onGenericMotionEvent before returning true.
11656            // This is to provide compatibility with existing applications that
11657            // handled HOVER_MOVE events in onGenericMotionEvent and that would
11658            // break because of the new default handling for hoverable views
11659            // in onHoverEvent.
11660            // Note that onGenericMotionEvent will be called by default when
11661            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
11662            dispatchGenericMotionEventInternal(event);
11663            // The event was already handled by calling setHovered(), so always
11664            // return true.
11665            return true;
11666        }
11667
11668        return false;
11669    }
11670
11671    /**
11672     * Returns true if the view should handle {@link #onHoverEvent}
11673     * by calling {@link #setHovered} to change its hovered state.
11674     *
11675     * @return True if the view is hoverable.
11676     */
11677    private boolean isHoverable() {
11678        final int viewFlags = mViewFlags;
11679        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11680            return false;
11681        }
11682
11683        return (viewFlags & CLICKABLE) == CLICKABLE
11684                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
11685                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
11686    }
11687
11688    /**
11689     * Returns true if the view is currently hovered.
11690     *
11691     * @return True if the view is currently hovered.
11692     *
11693     * @see #setHovered
11694     * @see #onHoverChanged
11695     */
11696    @ViewDebug.ExportedProperty
11697    public boolean isHovered() {
11698        return (mPrivateFlags & PFLAG_HOVERED) != 0;
11699    }
11700
11701    /**
11702     * Sets whether the view is currently hovered.
11703     * <p>
11704     * Calling this method also changes the drawable state of the view.  This
11705     * enables the view to react to hover by using different drawable resources
11706     * to change its appearance.
11707     * </p><p>
11708     * The {@link #onHoverChanged} method is called when the hovered state changes.
11709     * </p>
11710     *
11711     * @param hovered True if the view is hovered.
11712     *
11713     * @see #isHovered
11714     * @see #onHoverChanged
11715     */
11716    public void setHovered(boolean hovered) {
11717        if (hovered) {
11718            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
11719                mPrivateFlags |= PFLAG_HOVERED;
11720                refreshDrawableState();
11721                onHoverChanged(true);
11722            }
11723        } else {
11724            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
11725                mPrivateFlags &= ~PFLAG_HOVERED;
11726                refreshDrawableState();
11727                onHoverChanged(false);
11728            }
11729        }
11730    }
11731
11732    /**
11733     * Implement this method to handle hover state changes.
11734     * <p>
11735     * This method is called whenever the hover state changes as a result of a
11736     * call to {@link #setHovered}.
11737     * </p>
11738     *
11739     * @param hovered The current hover state, as returned by {@link #isHovered}.
11740     *
11741     * @see #isHovered
11742     * @see #setHovered
11743     */
11744    public void onHoverChanged(boolean hovered) {
11745    }
11746
11747    /**
11748     * Handles scroll bar dragging by mouse input.
11749     *
11750     * @hide
11751     * @param event The motion event.
11752     *
11753     * @return true if the event was handled as a scroll bar dragging, false otherwise.
11754     */
11755    protected boolean handleScrollBarDragging(MotionEvent event) {
11756        if (mScrollCache == null) {
11757            return false;
11758        }
11759        final float x = event.getX();
11760        final float y = event.getY();
11761        final int action = event.getAction();
11762        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
11763                && action != MotionEvent.ACTION_DOWN)
11764                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
11765                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
11766            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11767            return false;
11768        }
11769
11770        switch (action) {
11771            case MotionEvent.ACTION_MOVE:
11772                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
11773                    return false;
11774                }
11775                if (mScrollCache.mScrollBarDraggingState
11776                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
11777                    final Rect bounds = mScrollCache.mScrollBarBounds;
11778                    getVerticalScrollBarBounds(bounds, null);
11779                    final int range = computeVerticalScrollRange();
11780                    final int offset = computeVerticalScrollOffset();
11781                    final int extent = computeVerticalScrollExtent();
11782
11783                    final int thumbLength = ScrollBarUtils.getThumbLength(
11784                            bounds.height(), bounds.width(), extent, range);
11785                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11786                            bounds.height(), thumbLength, extent, range, offset);
11787
11788                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
11789                    final float maxThumbOffset = bounds.height() - thumbLength;
11790                    final float newThumbOffset =
11791                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11792                    final int height = getHeight();
11793                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11794                            && height > 0 && extent > 0) {
11795                        final int newY = Math.round((range - extent)
11796                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
11797                        if (newY != getScrollY()) {
11798                            mScrollCache.mScrollBarDraggingPos = y;
11799                            setScrollY(newY);
11800                        }
11801                    }
11802                    return true;
11803                }
11804                if (mScrollCache.mScrollBarDraggingState
11805                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
11806                    final Rect bounds = mScrollCache.mScrollBarBounds;
11807                    getHorizontalScrollBarBounds(bounds, null);
11808                    final int range = computeHorizontalScrollRange();
11809                    final int offset = computeHorizontalScrollOffset();
11810                    final int extent = computeHorizontalScrollExtent();
11811
11812                    final int thumbLength = ScrollBarUtils.getThumbLength(
11813                            bounds.width(), bounds.height(), extent, range);
11814                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
11815                            bounds.width(), thumbLength, extent, range, offset);
11816
11817                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
11818                    final float maxThumbOffset = bounds.width() - thumbLength;
11819                    final float newThumbOffset =
11820                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
11821                    final int width = getWidth();
11822                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
11823                            && width > 0 && extent > 0) {
11824                        final int newX = Math.round((range - extent)
11825                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
11826                        if (newX != getScrollX()) {
11827                            mScrollCache.mScrollBarDraggingPos = x;
11828                            setScrollX(newX);
11829                        }
11830                    }
11831                    return true;
11832                }
11833            case MotionEvent.ACTION_DOWN:
11834                if (mScrollCache.state == ScrollabilityCache.OFF) {
11835                    return false;
11836                }
11837                if (isOnVerticalScrollbarThumb(x, y)) {
11838                    mScrollCache.mScrollBarDraggingState =
11839                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
11840                    mScrollCache.mScrollBarDraggingPos = y;
11841                    return true;
11842                }
11843                if (isOnHorizontalScrollbarThumb(x, y)) {
11844                    mScrollCache.mScrollBarDraggingState =
11845                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
11846                    mScrollCache.mScrollBarDraggingPos = x;
11847                    return true;
11848                }
11849        }
11850        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
11851        return false;
11852    }
11853
11854    /**
11855     * Implement this method to handle touch screen motion events.
11856     * <p>
11857     * If this method is used to detect click actions, it is recommended that
11858     * the actions be performed by implementing and calling
11859     * {@link #performClick()}. This will ensure consistent system behavior,
11860     * including:
11861     * <ul>
11862     * <li>obeying click sound preferences
11863     * <li>dispatching OnClickListener calls
11864     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
11865     * accessibility features are enabled
11866     * </ul>
11867     *
11868     * @param event The motion event.
11869     * @return True if the event was handled, false otherwise.
11870     */
11871    public boolean onTouchEvent(MotionEvent event) {
11872        final float x = event.getX();
11873        final float y = event.getY();
11874        final int viewFlags = mViewFlags;
11875        final int action = event.getAction();
11876
11877        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
11878                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
11879                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
11880
11881        if ((viewFlags & ENABLED_MASK) == DISABLED) {
11882            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
11883                setPressed(false);
11884            }
11885            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11886            // A disabled view that is clickable still consumes the touch
11887            // events, it just doesn't respond to them.
11888            return clickable;
11889        }
11890        if (mTouchDelegate != null) {
11891            if (mTouchDelegate.onTouchEvent(event)) {
11892                return true;
11893            }
11894        }
11895
11896        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
11897            switch (action) {
11898                case MotionEvent.ACTION_UP:
11899                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11900                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
11901                        handleTooltipUp();
11902                    }
11903                    if (!clickable) {
11904                        removeTapCallback();
11905                        removeLongPressCallback();
11906                        mInContextButtonPress = false;
11907                        mHasPerformedLongPress = false;
11908                        mIgnoreNextUpEvent = false;
11909                        break;
11910                    }
11911                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
11912                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
11913                        // take focus if we don't have it already and we should in
11914                        // touch mode.
11915                        boolean focusTaken = false;
11916                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
11917                            focusTaken = requestFocus();
11918                        }
11919
11920                        if (prepressed) {
11921                            // The button is being released before we actually
11922                            // showed it as pressed.  Make it show the pressed
11923                            // state now (before scheduling the click) to ensure
11924                            // the user sees it.
11925                            setPressed(true, x, y);
11926                        }
11927
11928                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
11929                            // This is a tap, so remove the longpress check
11930                            removeLongPressCallback();
11931
11932                            // Only perform take click actions if we were in the pressed state
11933                            if (!focusTaken) {
11934                                // Use a Runnable and post this rather than calling
11935                                // performClick directly. This lets other visual state
11936                                // of the view update before click actions start.
11937                                if (mPerformClick == null) {
11938                                    mPerformClick = new PerformClick();
11939                                }
11940                                if (!post(mPerformClick)) {
11941                                    performClick();
11942                                }
11943                            }
11944                        }
11945
11946                        if (mUnsetPressedState == null) {
11947                            mUnsetPressedState = new UnsetPressedState();
11948                        }
11949
11950                        if (prepressed) {
11951                            postDelayed(mUnsetPressedState,
11952                                    ViewConfiguration.getPressedStateDuration());
11953                        } else if (!post(mUnsetPressedState)) {
11954                            // If the post failed, unpress right now
11955                            mUnsetPressedState.run();
11956                        }
11957
11958                        removeTapCallback();
11959                    }
11960                    mIgnoreNextUpEvent = false;
11961                    break;
11962
11963                case MotionEvent.ACTION_DOWN:
11964                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
11965                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
11966                    }
11967                    mHasPerformedLongPress = false;
11968
11969                    if (!clickable) {
11970                        checkForLongClick(0, x, y);
11971                        break;
11972                    }
11973
11974                    if (performButtonActionOnTouchDown(event)) {
11975                        break;
11976                    }
11977
11978                    // Walk up the hierarchy to determine if we're inside a scrolling container.
11979                    boolean isInScrollingContainer = isInScrollingContainer();
11980
11981                    // For views inside a scrolling container, delay the pressed feedback for
11982                    // a short period in case this is a scroll.
11983                    if (isInScrollingContainer) {
11984                        mPrivateFlags |= PFLAG_PREPRESSED;
11985                        if (mPendingCheckForTap == null) {
11986                            mPendingCheckForTap = new CheckForTap();
11987                        }
11988                        mPendingCheckForTap.x = event.getX();
11989                        mPendingCheckForTap.y = event.getY();
11990                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
11991                    } else {
11992                        // Not inside a scrolling container, so show the feedback right away
11993                        setPressed(true, x, y);
11994                        checkForLongClick(0, x, y);
11995                    }
11996                    break;
11997
11998                case MotionEvent.ACTION_CANCEL:
11999                    if (clickable) {
12000                        setPressed(false);
12001                    }
12002                    removeTapCallback();
12003                    removeLongPressCallback();
12004                    mInContextButtonPress = false;
12005                    mHasPerformedLongPress = false;
12006                    mIgnoreNextUpEvent = false;
12007                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12008                    break;
12009
12010                case MotionEvent.ACTION_MOVE:
12011                    if (clickable) {
12012                        drawableHotspotChanged(x, y);
12013                    }
12014
12015                    // Be lenient about moving outside of buttons
12016                    if (!pointInView(x, y, mTouchSlop)) {
12017                        // Outside button
12018                        // Remove any future long press/tap checks
12019                        removeTapCallback();
12020                        removeLongPressCallback();
12021                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
12022                            setPressed(false);
12023                        }
12024                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12025                    }
12026                    break;
12027            }
12028
12029            return true;
12030        }
12031
12032        return false;
12033    }
12034
12035    /**
12036     * @hide
12037     */
12038    public boolean isInScrollingContainer() {
12039        ViewParent p = getParent();
12040        while (p != null && p instanceof ViewGroup) {
12041            if (((ViewGroup) p).shouldDelayChildPressedState()) {
12042                return true;
12043            }
12044            p = p.getParent();
12045        }
12046        return false;
12047    }
12048
12049    /**
12050     * Remove the longpress detection timer.
12051     */
12052    private void removeLongPressCallback() {
12053        if (mPendingCheckForLongPress != null) {
12054            removeCallbacks(mPendingCheckForLongPress);
12055        }
12056    }
12057
12058    /**
12059     * Remove the pending click action
12060     */
12061    private void removePerformClickCallback() {
12062        if (mPerformClick != null) {
12063            removeCallbacks(mPerformClick);
12064        }
12065    }
12066
12067    /**
12068     * Remove the prepress detection timer.
12069     */
12070    private void removeUnsetPressCallback() {
12071        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
12072            setPressed(false);
12073            removeCallbacks(mUnsetPressedState);
12074        }
12075    }
12076
12077    /**
12078     * Remove the tap detection timer.
12079     */
12080    private void removeTapCallback() {
12081        if (mPendingCheckForTap != null) {
12082            mPrivateFlags &= ~PFLAG_PREPRESSED;
12083            removeCallbacks(mPendingCheckForTap);
12084        }
12085    }
12086
12087    /**
12088     * Cancels a pending long press.  Your subclass can use this if you
12089     * want the context menu to come up if the user presses and holds
12090     * at the same place, but you don't want it to come up if they press
12091     * and then move around enough to cause scrolling.
12092     */
12093    public void cancelLongPress() {
12094        removeLongPressCallback();
12095
12096        /*
12097         * The prepressed state handled by the tap callback is a display
12098         * construct, but the tap callback will post a long press callback
12099         * less its own timeout. Remove it here.
12100         */
12101        removeTapCallback();
12102    }
12103
12104    /**
12105     * Remove the pending callback for sending a
12106     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
12107     */
12108    private void removeSendViewScrolledAccessibilityEventCallback() {
12109        if (mSendViewScrolledAccessibilityEvent != null) {
12110            removeCallbacks(mSendViewScrolledAccessibilityEvent);
12111            mSendViewScrolledAccessibilityEvent.mIsPending = false;
12112        }
12113    }
12114
12115    /**
12116     * Sets the TouchDelegate for this View.
12117     */
12118    public void setTouchDelegate(TouchDelegate delegate) {
12119        mTouchDelegate = delegate;
12120    }
12121
12122    /**
12123     * Gets the TouchDelegate for this View.
12124     */
12125    public TouchDelegate getTouchDelegate() {
12126        return mTouchDelegate;
12127    }
12128
12129    /**
12130     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
12131     *
12132     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
12133     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
12134     * available. This method should only be called for touch events.
12135     *
12136     * <p class="note">This api is not intended for most applications. Buffered dispatch
12137     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
12138     * streams will not improve your input latency. Side effects include: increased latency,
12139     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
12140     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
12141     * you.</p>
12142     */
12143    public final void requestUnbufferedDispatch(MotionEvent event) {
12144        final int action = event.getAction();
12145        if (mAttachInfo == null
12146                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
12147                || !event.isTouchEvent()) {
12148            return;
12149        }
12150        mAttachInfo.mUnbufferedDispatchRequested = true;
12151    }
12152
12153    /**
12154     * Set flags controlling behavior of this view.
12155     *
12156     * @param flags Constant indicating the value which should be set
12157     * @param mask Constant indicating the bit range that should be changed
12158     */
12159    void setFlags(int flags, int mask) {
12160        final boolean accessibilityEnabled =
12161                AccessibilityManager.getInstance(mContext).isEnabled();
12162        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
12163
12164        int old = mViewFlags;
12165        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
12166
12167        int changed = mViewFlags ^ old;
12168        if (changed == 0) {
12169            return;
12170        }
12171        int privateFlags = mPrivateFlags;
12172
12173        // If focusable is auto, update the FOCUSABLE bit.
12174        int focusableChangedByAuto = 0;
12175        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
12176                && (changed & (FOCUSABLE_MASK | CLICKABLE | FOCUSABLE_IN_TOUCH_MODE)) != 0) {
12177            int newFocus = NOT_FOCUSABLE;
12178            if ((mViewFlags & (CLICKABLE | FOCUSABLE_IN_TOUCH_MODE)) != 0) {
12179                newFocus = FOCUSABLE;
12180            } else {
12181                mViewFlags = (mViewFlags & ~FOCUSABLE_IN_TOUCH_MODE);
12182            }
12183            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
12184            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
12185            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
12186        }
12187
12188        /* Check if the FOCUSABLE bit has changed */
12189        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
12190            if (((old & FOCUSABLE) == FOCUSABLE)
12191                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
12192                /* Give up focus if we are no longer focusable */
12193                clearFocus();
12194            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
12195                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
12196                /*
12197                 * Tell the view system that we are now available to take focus
12198                 * if no one else already has it.
12199                 */
12200                if (mParent != null) {
12201                    ViewRootImpl viewRootImpl = getViewRootImpl();
12202                    if (!sAutoFocusableOffUIThreadWontNotifyParents
12203                            || focusableChangedByAuto == 0
12204                            || viewRootImpl == null
12205                            || viewRootImpl.mThread == Thread.currentThread()) {
12206                        mParent.focusableViewAvailable(this);
12207                    }
12208                }
12209            }
12210        }
12211
12212        final int newVisibility = flags & VISIBILITY_MASK;
12213        if (newVisibility == VISIBLE) {
12214            if ((changed & VISIBILITY_MASK) != 0) {
12215                /*
12216                 * If this view is becoming visible, invalidate it in case it changed while
12217                 * it was not visible. Marking it drawn ensures that the invalidation will
12218                 * go through.
12219                 */
12220                mPrivateFlags |= PFLAG_DRAWN;
12221                invalidate(true);
12222
12223                needGlobalAttributesUpdate(true);
12224
12225                // a view becoming visible is worth notifying the parent
12226                // about in case nothing has focus.  even if this specific view
12227                // isn't focusable, it may contain something that is, so let
12228                // the root view try to give this focus if nothing else does.
12229                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
12230                    mParent.focusableViewAvailable(this);
12231                }
12232            }
12233        }
12234
12235        /* Check if the GONE bit has changed */
12236        if ((changed & GONE) != 0) {
12237            needGlobalAttributesUpdate(false);
12238            requestLayout();
12239
12240            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
12241                if (hasFocus()) clearFocus();
12242                clearAccessibilityFocus();
12243                destroyDrawingCache();
12244                if (mParent instanceof View) {
12245                    // GONE views noop invalidation, so invalidate the parent
12246                    ((View) mParent).invalidate(true);
12247                }
12248                // Mark the view drawn to ensure that it gets invalidated properly the next
12249                // time it is visible and gets invalidated
12250                mPrivateFlags |= PFLAG_DRAWN;
12251            }
12252            if (mAttachInfo != null) {
12253                mAttachInfo.mViewVisibilityChanged = true;
12254            }
12255        }
12256
12257        /* Check if the VISIBLE bit has changed */
12258        if ((changed & INVISIBLE) != 0) {
12259            needGlobalAttributesUpdate(false);
12260            /*
12261             * If this view is becoming invisible, set the DRAWN flag so that
12262             * the next invalidate() will not be skipped.
12263             */
12264            mPrivateFlags |= PFLAG_DRAWN;
12265
12266            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
12267                // root view becoming invisible shouldn't clear focus and accessibility focus
12268                if (getRootView() != this) {
12269                    if (hasFocus()) clearFocus();
12270                    clearAccessibilityFocus();
12271                }
12272            }
12273            if (mAttachInfo != null) {
12274                mAttachInfo.mViewVisibilityChanged = true;
12275            }
12276        }
12277
12278        if ((changed & VISIBILITY_MASK) != 0) {
12279            // If the view is invisible, cleanup its display list to free up resources
12280            if (newVisibility != VISIBLE && mAttachInfo != null) {
12281                cleanupDraw();
12282            }
12283
12284            if (mParent instanceof ViewGroup) {
12285                ((ViewGroup) mParent).onChildVisibilityChanged(this,
12286                        (changed & VISIBILITY_MASK), newVisibility);
12287                ((View) mParent).invalidate(true);
12288            } else if (mParent != null) {
12289                mParent.invalidateChild(this, null);
12290            }
12291
12292            if (mAttachInfo != null) {
12293                dispatchVisibilityChanged(this, newVisibility);
12294
12295                // Aggregated visibility changes are dispatched to attached views
12296                // in visible windows where the parent is currently shown/drawn
12297                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
12298                // discounting clipping or overlapping. This makes it a good place
12299                // to change animation states.
12300                if (mParent != null && getWindowVisibility() == VISIBLE &&
12301                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
12302                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
12303                }
12304                notifySubtreeAccessibilityStateChangedIfNeeded();
12305            }
12306        }
12307
12308        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
12309            destroyDrawingCache();
12310        }
12311
12312        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
12313            destroyDrawingCache();
12314            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12315            invalidateParentCaches();
12316        }
12317
12318        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
12319            destroyDrawingCache();
12320            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12321        }
12322
12323        if ((changed & DRAW_MASK) != 0) {
12324            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
12325                if (mBackground != null
12326                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
12327                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12328                } else {
12329                    mPrivateFlags |= PFLAG_SKIP_DRAW;
12330                }
12331            } else {
12332                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12333            }
12334            requestLayout();
12335            invalidate(true);
12336        }
12337
12338        if ((changed & KEEP_SCREEN_ON) != 0) {
12339            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
12340                mParent.recomputeViewAttributes(this);
12341            }
12342        }
12343
12344        if (accessibilityEnabled) {
12345            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
12346                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
12347                    || (changed & CONTEXT_CLICKABLE) != 0) {
12348                if (oldIncludeForAccessibility != includeForAccessibility()) {
12349                    notifySubtreeAccessibilityStateChangedIfNeeded();
12350                } else {
12351                    notifyViewAccessibilityStateChangedIfNeeded(
12352                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12353                }
12354            } else if ((changed & ENABLED_MASK) != 0) {
12355                notifyViewAccessibilityStateChangedIfNeeded(
12356                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
12357            }
12358        }
12359    }
12360
12361    /**
12362     * Change the view's z order in the tree, so it's on top of other sibling
12363     * views. This ordering change may affect layout, if the parent container
12364     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
12365     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
12366     * method should be followed by calls to {@link #requestLayout()} and
12367     * {@link View#invalidate()} on the view's parent to force the parent to redraw
12368     * with the new child ordering.
12369     *
12370     * @see ViewGroup#bringChildToFront(View)
12371     */
12372    public void bringToFront() {
12373        if (mParent != null) {
12374            mParent.bringChildToFront(this);
12375        }
12376    }
12377
12378    /**
12379     * This is called in response to an internal scroll in this view (i.e., the
12380     * view scrolled its own contents). This is typically as a result of
12381     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
12382     * called.
12383     *
12384     * @param l Current horizontal scroll origin.
12385     * @param t Current vertical scroll origin.
12386     * @param oldl Previous horizontal scroll origin.
12387     * @param oldt Previous vertical scroll origin.
12388     */
12389    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
12390        notifySubtreeAccessibilityStateChangedIfNeeded();
12391
12392        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
12393            postSendViewScrolledAccessibilityEventCallback();
12394        }
12395
12396        mBackgroundSizeChanged = true;
12397        if (mForegroundInfo != null) {
12398            mForegroundInfo.mBoundsChanged = true;
12399        }
12400
12401        final AttachInfo ai = mAttachInfo;
12402        if (ai != null) {
12403            ai.mViewScrollChanged = true;
12404        }
12405
12406        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
12407            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
12408        }
12409    }
12410
12411    /**
12412     * Interface definition for a callback to be invoked when the scroll
12413     * X or Y positions of a view change.
12414     * <p>
12415     * <b>Note:</b> Some views handle scrolling independently from View and may
12416     * have their own separate listeners for scroll-type events. For example,
12417     * {@link android.widget.ListView ListView} allows clients to register an
12418     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
12419     * to listen for changes in list scroll position.
12420     *
12421     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
12422     */
12423    public interface OnScrollChangeListener {
12424        /**
12425         * Called when the scroll position of a view changes.
12426         *
12427         * @param v The view whose scroll position has changed.
12428         * @param scrollX Current horizontal scroll origin.
12429         * @param scrollY Current vertical scroll origin.
12430         * @param oldScrollX Previous horizontal scroll origin.
12431         * @param oldScrollY Previous vertical scroll origin.
12432         */
12433        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
12434    }
12435
12436    /**
12437     * Interface definition for a callback to be invoked when the layout bounds of a view
12438     * changes due to layout processing.
12439     */
12440    public interface OnLayoutChangeListener {
12441        /**
12442         * Called when the layout bounds of a view changes due to layout processing.
12443         *
12444         * @param v The view whose bounds have changed.
12445         * @param left The new value of the view's left property.
12446         * @param top The new value of the view's top property.
12447         * @param right The new value of the view's right property.
12448         * @param bottom The new value of the view's bottom property.
12449         * @param oldLeft The previous value of the view's left property.
12450         * @param oldTop The previous value of the view's top property.
12451         * @param oldRight The previous value of the view's right property.
12452         * @param oldBottom The previous value of the view's bottom property.
12453         */
12454        void onLayoutChange(View v, int left, int top, int right, int bottom,
12455            int oldLeft, int oldTop, int oldRight, int oldBottom);
12456    }
12457
12458    /**
12459     * This is called during layout when the size of this view has changed. If
12460     * you were just added to the view hierarchy, you're called with the old
12461     * values of 0.
12462     *
12463     * @param w Current width of this view.
12464     * @param h Current height of this view.
12465     * @param oldw Old width of this view.
12466     * @param oldh Old height of this view.
12467     */
12468    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
12469    }
12470
12471    /**
12472     * Called by draw to draw the child views. This may be overridden
12473     * by derived classes to gain control just before its children are drawn
12474     * (but after its own view has been drawn).
12475     * @param canvas the canvas on which to draw the view
12476     */
12477    protected void dispatchDraw(Canvas canvas) {
12478
12479    }
12480
12481    /**
12482     * Gets the parent of this view. Note that the parent is a
12483     * ViewParent and not necessarily a View.
12484     *
12485     * @return Parent of this view.
12486     */
12487    public final ViewParent getParent() {
12488        return mParent;
12489    }
12490
12491    /**
12492     * Set the horizontal scrolled position of your view. This will cause a call to
12493     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12494     * invalidated.
12495     * @param value the x position to scroll to
12496     */
12497    public void setScrollX(int value) {
12498        scrollTo(value, mScrollY);
12499    }
12500
12501    /**
12502     * Set the vertical scrolled position of your view. This will cause a call to
12503     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12504     * invalidated.
12505     * @param value the y position to scroll to
12506     */
12507    public void setScrollY(int value) {
12508        scrollTo(mScrollX, value);
12509    }
12510
12511    /**
12512     * Return the scrolled left position of this view. This is the left edge of
12513     * the displayed part of your view. You do not need to draw any pixels
12514     * farther left, since those are outside of the frame of your view on
12515     * screen.
12516     *
12517     * @return The left edge of the displayed part of your view, in pixels.
12518     */
12519    public final int getScrollX() {
12520        return mScrollX;
12521    }
12522
12523    /**
12524     * Return the scrolled top position of this view. This is the top edge of
12525     * the displayed part of your view. You do not need to draw any pixels above
12526     * it, since those are outside of the frame of your view on screen.
12527     *
12528     * @return The top edge of the displayed part of your view, in pixels.
12529     */
12530    public final int getScrollY() {
12531        return mScrollY;
12532    }
12533
12534    /**
12535     * Return the width of the your view.
12536     *
12537     * @return The width of your view, in pixels.
12538     */
12539    @ViewDebug.ExportedProperty(category = "layout")
12540    public final int getWidth() {
12541        return mRight - mLeft;
12542    }
12543
12544    /**
12545     * Return the height of your view.
12546     *
12547     * @return The height of your view, in pixels.
12548     */
12549    @ViewDebug.ExportedProperty(category = "layout")
12550    public final int getHeight() {
12551        return mBottom - mTop;
12552    }
12553
12554    /**
12555     * Return the visible drawing bounds of your view. Fills in the output
12556     * rectangle with the values from getScrollX(), getScrollY(),
12557     * getWidth(), and getHeight(). These bounds do not account for any
12558     * transformation properties currently set on the view, such as
12559     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
12560     *
12561     * @param outRect The (scrolled) drawing bounds of the view.
12562     */
12563    public void getDrawingRect(Rect outRect) {
12564        outRect.left = mScrollX;
12565        outRect.top = mScrollY;
12566        outRect.right = mScrollX + (mRight - mLeft);
12567        outRect.bottom = mScrollY + (mBottom - mTop);
12568    }
12569
12570    /**
12571     * Like {@link #getMeasuredWidthAndState()}, but only returns the
12572     * raw width component (that is the result is masked by
12573     * {@link #MEASURED_SIZE_MASK}).
12574     *
12575     * @return The raw measured width of this view.
12576     */
12577    public final int getMeasuredWidth() {
12578        return mMeasuredWidth & MEASURED_SIZE_MASK;
12579    }
12580
12581    /**
12582     * Return the full width measurement information for this view as computed
12583     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
12584     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
12585     * This should be used during measurement and layout calculations only. Use
12586     * {@link #getWidth()} to see how wide a view is after layout.
12587     *
12588     * @return The measured width of this view as a bit mask.
12589     */
12590    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
12591            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
12592                    name = "MEASURED_STATE_TOO_SMALL"),
12593    })
12594    public final int getMeasuredWidthAndState() {
12595        return mMeasuredWidth;
12596    }
12597
12598    /**
12599     * Like {@link #getMeasuredHeightAndState()}, but only returns the
12600     * raw height component (that is the result is masked by
12601     * {@link #MEASURED_SIZE_MASK}).
12602     *
12603     * @return The raw measured height of this view.
12604     */
12605    public final int getMeasuredHeight() {
12606        return mMeasuredHeight & MEASURED_SIZE_MASK;
12607    }
12608
12609    /**
12610     * Return the full height measurement information for this view as computed
12611     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
12612     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
12613     * This should be used during measurement and layout calculations only. Use
12614     * {@link #getHeight()} to see how wide a view is after layout.
12615     *
12616     * @return The measured height of this view as a bit mask.
12617     */
12618    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
12619            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
12620                    name = "MEASURED_STATE_TOO_SMALL"),
12621    })
12622    public final int getMeasuredHeightAndState() {
12623        return mMeasuredHeight;
12624    }
12625
12626    /**
12627     * Return only the state bits of {@link #getMeasuredWidthAndState()}
12628     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
12629     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
12630     * and the height component is at the shifted bits
12631     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
12632     */
12633    public final int getMeasuredState() {
12634        return (mMeasuredWidth&MEASURED_STATE_MASK)
12635                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
12636                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
12637    }
12638
12639    /**
12640     * The transform matrix of this view, which is calculated based on the current
12641     * rotation, scale, and pivot properties.
12642     *
12643     * @see #getRotation()
12644     * @see #getScaleX()
12645     * @see #getScaleY()
12646     * @see #getPivotX()
12647     * @see #getPivotY()
12648     * @return The current transform matrix for the view
12649     */
12650    public Matrix getMatrix() {
12651        ensureTransformationInfo();
12652        final Matrix matrix = mTransformationInfo.mMatrix;
12653        mRenderNode.getMatrix(matrix);
12654        return matrix;
12655    }
12656
12657    /**
12658     * Returns true if the transform matrix is the identity matrix.
12659     * Recomputes the matrix if necessary.
12660     *
12661     * @return True if the transform matrix is the identity matrix, false otherwise.
12662     */
12663    final boolean hasIdentityMatrix() {
12664        return mRenderNode.hasIdentityMatrix();
12665    }
12666
12667    void ensureTransformationInfo() {
12668        if (mTransformationInfo == null) {
12669            mTransformationInfo = new TransformationInfo();
12670        }
12671    }
12672
12673    /**
12674     * Utility method to retrieve the inverse of the current mMatrix property.
12675     * We cache the matrix to avoid recalculating it when transform properties
12676     * have not changed.
12677     *
12678     * @return The inverse of the current matrix of this view.
12679     * @hide
12680     */
12681    public final Matrix getInverseMatrix() {
12682        ensureTransformationInfo();
12683        if (mTransformationInfo.mInverseMatrix == null) {
12684            mTransformationInfo.mInverseMatrix = new Matrix();
12685        }
12686        final Matrix matrix = mTransformationInfo.mInverseMatrix;
12687        mRenderNode.getInverseMatrix(matrix);
12688        return matrix;
12689    }
12690
12691    /**
12692     * Gets the distance along the Z axis from the camera to this view.
12693     *
12694     * @see #setCameraDistance(float)
12695     *
12696     * @return The distance along the Z axis.
12697     */
12698    public float getCameraDistance() {
12699        final float dpi = mResources.getDisplayMetrics().densityDpi;
12700        return -(mRenderNode.getCameraDistance() * dpi);
12701    }
12702
12703    /**
12704     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
12705     * views are drawn) from the camera to this view. The camera's distance
12706     * affects 3D transformations, for instance rotations around the X and Y
12707     * axis. If the rotationX or rotationY properties are changed and this view is
12708     * large (more than half the size of the screen), it is recommended to always
12709     * use a camera distance that's greater than the height (X axis rotation) or
12710     * the width (Y axis rotation) of this view.</p>
12711     *
12712     * <p>The distance of the camera from the view plane can have an affect on the
12713     * perspective distortion of the view when it is rotated around the x or y axis.
12714     * For example, a large distance will result in a large viewing angle, and there
12715     * will not be much perspective distortion of the view as it rotates. A short
12716     * distance may cause much more perspective distortion upon rotation, and can
12717     * also result in some drawing artifacts if the rotated view ends up partially
12718     * behind the camera (which is why the recommendation is to use a distance at
12719     * least as far as the size of the view, if the view is to be rotated.)</p>
12720     *
12721     * <p>The distance is expressed in "depth pixels." The default distance depends
12722     * on the screen density. For instance, on a medium density display, the
12723     * default distance is 1280. On a high density display, the default distance
12724     * is 1920.</p>
12725     *
12726     * <p>If you want to specify a distance that leads to visually consistent
12727     * results across various densities, use the following formula:</p>
12728     * <pre>
12729     * float scale = context.getResources().getDisplayMetrics().density;
12730     * view.setCameraDistance(distance * scale);
12731     * </pre>
12732     *
12733     * <p>The density scale factor of a high density display is 1.5,
12734     * and 1920 = 1280 * 1.5.</p>
12735     *
12736     * @param distance The distance in "depth pixels", if negative the opposite
12737     *        value is used
12738     *
12739     * @see #setRotationX(float)
12740     * @see #setRotationY(float)
12741     */
12742    public void setCameraDistance(float distance) {
12743        final float dpi = mResources.getDisplayMetrics().densityDpi;
12744
12745        invalidateViewProperty(true, false);
12746        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
12747        invalidateViewProperty(false, false);
12748
12749        invalidateParentIfNeededAndWasQuickRejected();
12750    }
12751
12752    /**
12753     * The degrees that the view is rotated around the pivot point.
12754     *
12755     * @see #setRotation(float)
12756     * @see #getPivotX()
12757     * @see #getPivotY()
12758     *
12759     * @return The degrees of rotation.
12760     */
12761    @ViewDebug.ExportedProperty(category = "drawing")
12762    public float getRotation() {
12763        return mRenderNode.getRotation();
12764    }
12765
12766    /**
12767     * Sets the degrees that the view is rotated around the pivot point. Increasing values
12768     * result in clockwise rotation.
12769     *
12770     * @param rotation The degrees of rotation.
12771     *
12772     * @see #getRotation()
12773     * @see #getPivotX()
12774     * @see #getPivotY()
12775     * @see #setRotationX(float)
12776     * @see #setRotationY(float)
12777     *
12778     * @attr ref android.R.styleable#View_rotation
12779     */
12780    public void setRotation(float rotation) {
12781        if (rotation != getRotation()) {
12782            // Double-invalidation is necessary to capture view's old and new areas
12783            invalidateViewProperty(true, false);
12784            mRenderNode.setRotation(rotation);
12785            invalidateViewProperty(false, true);
12786
12787            invalidateParentIfNeededAndWasQuickRejected();
12788            notifySubtreeAccessibilityStateChangedIfNeeded();
12789        }
12790    }
12791
12792    /**
12793     * The degrees that the view is rotated around the vertical axis through the pivot point.
12794     *
12795     * @see #getPivotX()
12796     * @see #getPivotY()
12797     * @see #setRotationY(float)
12798     *
12799     * @return The degrees of Y rotation.
12800     */
12801    @ViewDebug.ExportedProperty(category = "drawing")
12802    public float getRotationY() {
12803        return mRenderNode.getRotationY();
12804    }
12805
12806    /**
12807     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
12808     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
12809     * down the y axis.
12810     *
12811     * When rotating large views, it is recommended to adjust the camera distance
12812     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12813     *
12814     * @param rotationY The degrees of Y rotation.
12815     *
12816     * @see #getRotationY()
12817     * @see #getPivotX()
12818     * @see #getPivotY()
12819     * @see #setRotation(float)
12820     * @see #setRotationX(float)
12821     * @see #setCameraDistance(float)
12822     *
12823     * @attr ref android.R.styleable#View_rotationY
12824     */
12825    public void setRotationY(float rotationY) {
12826        if (rotationY != getRotationY()) {
12827            invalidateViewProperty(true, false);
12828            mRenderNode.setRotationY(rotationY);
12829            invalidateViewProperty(false, true);
12830
12831            invalidateParentIfNeededAndWasQuickRejected();
12832            notifySubtreeAccessibilityStateChangedIfNeeded();
12833        }
12834    }
12835
12836    /**
12837     * The degrees that the view is rotated around the horizontal axis through the pivot point.
12838     *
12839     * @see #getPivotX()
12840     * @see #getPivotY()
12841     * @see #setRotationX(float)
12842     *
12843     * @return The degrees of X rotation.
12844     */
12845    @ViewDebug.ExportedProperty(category = "drawing")
12846    public float getRotationX() {
12847        return mRenderNode.getRotationX();
12848    }
12849
12850    /**
12851     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
12852     * Increasing values result in clockwise rotation from the viewpoint of looking down the
12853     * x axis.
12854     *
12855     * When rotating large views, it is recommended to adjust the camera distance
12856     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
12857     *
12858     * @param rotationX The degrees of X rotation.
12859     *
12860     * @see #getRotationX()
12861     * @see #getPivotX()
12862     * @see #getPivotY()
12863     * @see #setRotation(float)
12864     * @see #setRotationY(float)
12865     * @see #setCameraDistance(float)
12866     *
12867     * @attr ref android.R.styleable#View_rotationX
12868     */
12869    public void setRotationX(float rotationX) {
12870        if (rotationX != getRotationX()) {
12871            invalidateViewProperty(true, false);
12872            mRenderNode.setRotationX(rotationX);
12873            invalidateViewProperty(false, true);
12874
12875            invalidateParentIfNeededAndWasQuickRejected();
12876            notifySubtreeAccessibilityStateChangedIfNeeded();
12877        }
12878    }
12879
12880    /**
12881     * The amount that the view is scaled in x around the pivot point, as a proportion of
12882     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
12883     *
12884     * <p>By default, this is 1.0f.
12885     *
12886     * @see #getPivotX()
12887     * @see #getPivotY()
12888     * @return The scaling factor.
12889     */
12890    @ViewDebug.ExportedProperty(category = "drawing")
12891    public float getScaleX() {
12892        return mRenderNode.getScaleX();
12893    }
12894
12895    /**
12896     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
12897     * the view's unscaled width. A value of 1 means that no scaling is applied.
12898     *
12899     * @param scaleX The scaling factor.
12900     * @see #getPivotX()
12901     * @see #getPivotY()
12902     *
12903     * @attr ref android.R.styleable#View_scaleX
12904     */
12905    public void setScaleX(float scaleX) {
12906        if (scaleX != getScaleX()) {
12907            invalidateViewProperty(true, false);
12908            mRenderNode.setScaleX(scaleX);
12909            invalidateViewProperty(false, true);
12910
12911            invalidateParentIfNeededAndWasQuickRejected();
12912            notifySubtreeAccessibilityStateChangedIfNeeded();
12913        }
12914    }
12915
12916    /**
12917     * The amount that the view is scaled in y around the pivot point, as a proportion of
12918     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
12919     *
12920     * <p>By default, this is 1.0f.
12921     *
12922     * @see #getPivotX()
12923     * @see #getPivotY()
12924     * @return The scaling factor.
12925     */
12926    @ViewDebug.ExportedProperty(category = "drawing")
12927    public float getScaleY() {
12928        return mRenderNode.getScaleY();
12929    }
12930
12931    /**
12932     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
12933     * the view's unscaled width. A value of 1 means that no scaling is applied.
12934     *
12935     * @param scaleY The scaling factor.
12936     * @see #getPivotX()
12937     * @see #getPivotY()
12938     *
12939     * @attr ref android.R.styleable#View_scaleY
12940     */
12941    public void setScaleY(float scaleY) {
12942        if (scaleY != getScaleY()) {
12943            invalidateViewProperty(true, false);
12944            mRenderNode.setScaleY(scaleY);
12945            invalidateViewProperty(false, true);
12946
12947            invalidateParentIfNeededAndWasQuickRejected();
12948            notifySubtreeAccessibilityStateChangedIfNeeded();
12949        }
12950    }
12951
12952    /**
12953     * The x location of the point around which the view is {@link #setRotation(float) rotated}
12954     * and {@link #setScaleX(float) scaled}.
12955     *
12956     * @see #getRotation()
12957     * @see #getScaleX()
12958     * @see #getScaleY()
12959     * @see #getPivotY()
12960     * @return The x location of the pivot point.
12961     *
12962     * @attr ref android.R.styleable#View_transformPivotX
12963     */
12964    @ViewDebug.ExportedProperty(category = "drawing")
12965    public float getPivotX() {
12966        return mRenderNode.getPivotX();
12967    }
12968
12969    /**
12970     * Sets the x location of the point around which the view is
12971     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
12972     * By default, the pivot point is centered on the object.
12973     * Setting this property disables this behavior and causes the view to use only the
12974     * explicitly set pivotX and pivotY values.
12975     *
12976     * @param pivotX The x location of the pivot point.
12977     * @see #getRotation()
12978     * @see #getScaleX()
12979     * @see #getScaleY()
12980     * @see #getPivotY()
12981     *
12982     * @attr ref android.R.styleable#View_transformPivotX
12983     */
12984    public void setPivotX(float pivotX) {
12985        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
12986            invalidateViewProperty(true, false);
12987            mRenderNode.setPivotX(pivotX);
12988            invalidateViewProperty(false, true);
12989
12990            invalidateParentIfNeededAndWasQuickRejected();
12991        }
12992    }
12993
12994    /**
12995     * The y location of the point around which the view is {@link #setRotation(float) rotated}
12996     * and {@link #setScaleY(float) scaled}.
12997     *
12998     * @see #getRotation()
12999     * @see #getScaleX()
13000     * @see #getScaleY()
13001     * @see #getPivotY()
13002     * @return The y location of the pivot point.
13003     *
13004     * @attr ref android.R.styleable#View_transformPivotY
13005     */
13006    @ViewDebug.ExportedProperty(category = "drawing")
13007    public float getPivotY() {
13008        return mRenderNode.getPivotY();
13009    }
13010
13011    /**
13012     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
13013     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
13014     * Setting this property disables this behavior and causes the view to use only the
13015     * explicitly set pivotX and pivotY values.
13016     *
13017     * @param pivotY The y location of the pivot point.
13018     * @see #getRotation()
13019     * @see #getScaleX()
13020     * @see #getScaleY()
13021     * @see #getPivotY()
13022     *
13023     * @attr ref android.R.styleable#View_transformPivotY
13024     */
13025    public void setPivotY(float pivotY) {
13026        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
13027            invalidateViewProperty(true, false);
13028            mRenderNode.setPivotY(pivotY);
13029            invalidateViewProperty(false, true);
13030
13031            invalidateParentIfNeededAndWasQuickRejected();
13032        }
13033    }
13034
13035    /**
13036     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
13037     * completely transparent and 1 means the view is completely opaque.
13038     *
13039     * <p>By default this is 1.0f.
13040     * @return The opacity of the view.
13041     */
13042    @ViewDebug.ExportedProperty(category = "drawing")
13043    public float getAlpha() {
13044        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
13045    }
13046
13047    /**
13048     * Sets the behavior for overlapping rendering for this view (see {@link
13049     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
13050     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
13051     * providing the value which is then used internally. That is, when {@link
13052     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
13053     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
13054     * instead.
13055     *
13056     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
13057     * instead of that returned by {@link #hasOverlappingRendering()}.
13058     *
13059     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
13060     */
13061    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
13062        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
13063        if (hasOverlappingRendering) {
13064            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13065        } else {
13066            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13067        }
13068    }
13069
13070    /**
13071     * Returns the value for overlapping rendering that is used internally. This is either
13072     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
13073     * the return value of {@link #hasOverlappingRendering()}, otherwise.
13074     *
13075     * @return The value for overlapping rendering being used internally.
13076     */
13077    public final boolean getHasOverlappingRendering() {
13078        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
13079                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
13080                hasOverlappingRendering();
13081    }
13082
13083    /**
13084     * Returns whether this View has content which overlaps.
13085     *
13086     * <p>This function, intended to be overridden by specific View types, is an optimization when
13087     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
13088     * an offscreen buffer and then composited into place, which can be expensive. If the view has
13089     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
13090     * directly. An example of overlapping rendering is a TextView with a background image, such as
13091     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
13092     * ImageView with only the foreground image. The default implementation returns true; subclasses
13093     * should override if they have cases which can be optimized.</p>
13094     *
13095     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
13096     * necessitates that a View return true if it uses the methods internally without passing the
13097     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
13098     *
13099     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
13100     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
13101     *
13102     * @return true if the content in this view might overlap, false otherwise.
13103     */
13104    @ViewDebug.ExportedProperty(category = "drawing")
13105    public boolean hasOverlappingRendering() {
13106        return true;
13107    }
13108
13109    /**
13110     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
13111     * completely transparent and 1 means the view is completely opaque.
13112     *
13113     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
13114     * can have significant performance implications, especially for large views. It is best to use
13115     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
13116     *
13117     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
13118     * strongly recommended for performance reasons to either override
13119     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
13120     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
13121     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
13122     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
13123     * of rendering cost, even for simple or small views. Starting with
13124     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
13125     * applied to the view at the rendering level.</p>
13126     *
13127     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
13128     * responsible for applying the opacity itself.</p>
13129     *
13130     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
13131     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
13132     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
13133     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
13134     *
13135     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
13136     * value will clip a View to its bounds, unless the View returns <code>false</code> from
13137     * {@link #hasOverlappingRendering}.</p>
13138     *
13139     * @param alpha The opacity of the view.
13140     *
13141     * @see #hasOverlappingRendering()
13142     * @see #setLayerType(int, android.graphics.Paint)
13143     *
13144     * @attr ref android.R.styleable#View_alpha
13145     */
13146    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
13147        ensureTransformationInfo();
13148        if (mTransformationInfo.mAlpha != alpha) {
13149            // Report visibility changes, which can affect children, to accessibility
13150            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
13151                notifySubtreeAccessibilityStateChangedIfNeeded();
13152            }
13153            mTransformationInfo.mAlpha = alpha;
13154            if (onSetAlpha((int) (alpha * 255))) {
13155                mPrivateFlags |= PFLAG_ALPHA_SET;
13156                // subclass is handling alpha - don't optimize rendering cache invalidation
13157                invalidateParentCaches();
13158                invalidate(true);
13159            } else {
13160                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13161                invalidateViewProperty(true, false);
13162                mRenderNode.setAlpha(getFinalAlpha());
13163            }
13164        }
13165    }
13166
13167    /**
13168     * Faster version of setAlpha() which performs the same steps except there are
13169     * no calls to invalidate(). The caller of this function should perform proper invalidation
13170     * on the parent and this object. The return value indicates whether the subclass handles
13171     * alpha (the return value for onSetAlpha()).
13172     *
13173     * @param alpha The new value for the alpha property
13174     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
13175     *         the new value for the alpha property is different from the old value
13176     */
13177    boolean setAlphaNoInvalidation(float alpha) {
13178        ensureTransformationInfo();
13179        if (mTransformationInfo.mAlpha != alpha) {
13180            mTransformationInfo.mAlpha = alpha;
13181            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
13182            if (subclassHandlesAlpha) {
13183                mPrivateFlags |= PFLAG_ALPHA_SET;
13184                return true;
13185            } else {
13186                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13187                mRenderNode.setAlpha(getFinalAlpha());
13188            }
13189        }
13190        return false;
13191    }
13192
13193    /**
13194     * This property is hidden and intended only for use by the Fade transition, which
13195     * animates it to produce a visual translucency that does not side-effect (or get
13196     * affected by) the real alpha property. This value is composited with the other
13197     * alpha value (and the AlphaAnimation value, when that is present) to produce
13198     * a final visual translucency result, which is what is passed into the DisplayList.
13199     *
13200     * @hide
13201     */
13202    public void setTransitionAlpha(float alpha) {
13203        ensureTransformationInfo();
13204        if (mTransformationInfo.mTransitionAlpha != alpha) {
13205            mTransformationInfo.mTransitionAlpha = alpha;
13206            mPrivateFlags &= ~PFLAG_ALPHA_SET;
13207            invalidateViewProperty(true, false);
13208            mRenderNode.setAlpha(getFinalAlpha());
13209        }
13210    }
13211
13212    /**
13213     * Calculates the visual alpha of this view, which is a combination of the actual
13214     * alpha value and the transitionAlpha value (if set).
13215     */
13216    private float getFinalAlpha() {
13217        if (mTransformationInfo != null) {
13218            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
13219        }
13220        return 1;
13221    }
13222
13223    /**
13224     * This property is hidden and intended only for use by the Fade transition, which
13225     * animates it to produce a visual translucency that does not side-effect (or get
13226     * affected by) the real alpha property. This value is composited with the other
13227     * alpha value (and the AlphaAnimation value, when that is present) to produce
13228     * a final visual translucency result, which is what is passed into the DisplayList.
13229     *
13230     * @hide
13231     */
13232    @ViewDebug.ExportedProperty(category = "drawing")
13233    public float getTransitionAlpha() {
13234        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
13235    }
13236
13237    /**
13238     * Top position of this view relative to its parent.
13239     *
13240     * @return The top of this view, in pixels.
13241     */
13242    @ViewDebug.CapturedViewProperty
13243    public final int getTop() {
13244        return mTop;
13245    }
13246
13247    /**
13248     * Sets the top position of this view relative to its parent. This method is meant to be called
13249     * by the layout system and should not generally be called otherwise, because the property
13250     * may be changed at any time by the layout.
13251     *
13252     * @param top The top of this view, in pixels.
13253     */
13254    public final void setTop(int top) {
13255        if (top != mTop) {
13256            final boolean matrixIsIdentity = hasIdentityMatrix();
13257            if (matrixIsIdentity) {
13258                if (mAttachInfo != null) {
13259                    int minTop;
13260                    int yLoc;
13261                    if (top < mTop) {
13262                        minTop = top;
13263                        yLoc = top - mTop;
13264                    } else {
13265                        minTop = mTop;
13266                        yLoc = 0;
13267                    }
13268                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
13269                }
13270            } else {
13271                // Double-invalidation is necessary to capture view's old and new areas
13272                invalidate(true);
13273            }
13274
13275            int width = mRight - mLeft;
13276            int oldHeight = mBottom - mTop;
13277
13278            mTop = top;
13279            mRenderNode.setTop(mTop);
13280
13281            sizeChange(width, mBottom - mTop, width, oldHeight);
13282
13283            if (!matrixIsIdentity) {
13284                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13285                invalidate(true);
13286            }
13287            mBackgroundSizeChanged = true;
13288            if (mForegroundInfo != null) {
13289                mForegroundInfo.mBoundsChanged = true;
13290            }
13291            invalidateParentIfNeeded();
13292            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13293                // View was rejected last time it was drawn by its parent; this may have changed
13294                invalidateParentIfNeeded();
13295            }
13296        }
13297    }
13298
13299    /**
13300     * Bottom position of this view relative to its parent.
13301     *
13302     * @return The bottom of this view, in pixels.
13303     */
13304    @ViewDebug.CapturedViewProperty
13305    public final int getBottom() {
13306        return mBottom;
13307    }
13308
13309    /**
13310     * True if this view has changed since the last time being drawn.
13311     *
13312     * @return The dirty state of this view.
13313     */
13314    public boolean isDirty() {
13315        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
13316    }
13317
13318    /**
13319     * Sets the bottom position of this view relative to its parent. This method is meant to be
13320     * called by the layout system and should not generally be called otherwise, because the
13321     * property may be changed at any time by the layout.
13322     *
13323     * @param bottom The bottom of this view, in pixels.
13324     */
13325    public final void setBottom(int bottom) {
13326        if (bottom != mBottom) {
13327            final boolean matrixIsIdentity = hasIdentityMatrix();
13328            if (matrixIsIdentity) {
13329                if (mAttachInfo != null) {
13330                    int maxBottom;
13331                    if (bottom < mBottom) {
13332                        maxBottom = mBottom;
13333                    } else {
13334                        maxBottom = bottom;
13335                    }
13336                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
13337                }
13338            } else {
13339                // Double-invalidation is necessary to capture view's old and new areas
13340                invalidate(true);
13341            }
13342
13343            int width = mRight - mLeft;
13344            int oldHeight = mBottom - mTop;
13345
13346            mBottom = bottom;
13347            mRenderNode.setBottom(mBottom);
13348
13349            sizeChange(width, mBottom - mTop, width, oldHeight);
13350
13351            if (!matrixIsIdentity) {
13352                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13353                invalidate(true);
13354            }
13355            mBackgroundSizeChanged = true;
13356            if (mForegroundInfo != null) {
13357                mForegroundInfo.mBoundsChanged = true;
13358            }
13359            invalidateParentIfNeeded();
13360            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13361                // View was rejected last time it was drawn by its parent; this may have changed
13362                invalidateParentIfNeeded();
13363            }
13364        }
13365    }
13366
13367    /**
13368     * Left position of this view relative to its parent.
13369     *
13370     * @return The left edge of this view, in pixels.
13371     */
13372    @ViewDebug.CapturedViewProperty
13373    public final int getLeft() {
13374        return mLeft;
13375    }
13376
13377    /**
13378     * Sets the left position of this view relative to its parent. This method is meant to be called
13379     * by the layout system and should not generally be called otherwise, because the property
13380     * may be changed at any time by the layout.
13381     *
13382     * @param left The left of this view, in pixels.
13383     */
13384    public final void setLeft(int left) {
13385        if (left != mLeft) {
13386            final boolean matrixIsIdentity = hasIdentityMatrix();
13387            if (matrixIsIdentity) {
13388                if (mAttachInfo != null) {
13389                    int minLeft;
13390                    int xLoc;
13391                    if (left < mLeft) {
13392                        minLeft = left;
13393                        xLoc = left - mLeft;
13394                    } else {
13395                        minLeft = mLeft;
13396                        xLoc = 0;
13397                    }
13398                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
13399                }
13400            } else {
13401                // Double-invalidation is necessary to capture view's old and new areas
13402                invalidate(true);
13403            }
13404
13405            int oldWidth = mRight - mLeft;
13406            int height = mBottom - mTop;
13407
13408            mLeft = left;
13409            mRenderNode.setLeft(left);
13410
13411            sizeChange(mRight - mLeft, height, oldWidth, height);
13412
13413            if (!matrixIsIdentity) {
13414                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13415                invalidate(true);
13416            }
13417            mBackgroundSizeChanged = true;
13418            if (mForegroundInfo != null) {
13419                mForegroundInfo.mBoundsChanged = true;
13420            }
13421            invalidateParentIfNeeded();
13422            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13423                // View was rejected last time it was drawn by its parent; this may have changed
13424                invalidateParentIfNeeded();
13425            }
13426        }
13427    }
13428
13429    /**
13430     * Right position of this view relative to its parent.
13431     *
13432     * @return The right edge of this view, in pixels.
13433     */
13434    @ViewDebug.CapturedViewProperty
13435    public final int getRight() {
13436        return mRight;
13437    }
13438
13439    /**
13440     * Sets the right position of this view relative to its parent. This method is meant to be called
13441     * by the layout system and should not generally be called otherwise, because the property
13442     * may be changed at any time by the layout.
13443     *
13444     * @param right The right of this view, in pixels.
13445     */
13446    public final void setRight(int right) {
13447        if (right != mRight) {
13448            final boolean matrixIsIdentity = hasIdentityMatrix();
13449            if (matrixIsIdentity) {
13450                if (mAttachInfo != null) {
13451                    int maxRight;
13452                    if (right < mRight) {
13453                        maxRight = mRight;
13454                    } else {
13455                        maxRight = right;
13456                    }
13457                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
13458                }
13459            } else {
13460                // Double-invalidation is necessary to capture view's old and new areas
13461                invalidate(true);
13462            }
13463
13464            int oldWidth = mRight - mLeft;
13465            int height = mBottom - mTop;
13466
13467            mRight = right;
13468            mRenderNode.setRight(mRight);
13469
13470            sizeChange(mRight - mLeft, height, oldWidth, height);
13471
13472            if (!matrixIsIdentity) {
13473                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13474                invalidate(true);
13475            }
13476            mBackgroundSizeChanged = true;
13477            if (mForegroundInfo != null) {
13478                mForegroundInfo.mBoundsChanged = true;
13479            }
13480            invalidateParentIfNeeded();
13481            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13482                // View was rejected last time it was drawn by its parent; this may have changed
13483                invalidateParentIfNeeded();
13484            }
13485        }
13486    }
13487
13488    /**
13489     * The visual x position of this view, in pixels. This is equivalent to the
13490     * {@link #setTranslationX(float) translationX} property plus the current
13491     * {@link #getLeft() left} property.
13492     *
13493     * @return The visual x position of this view, in pixels.
13494     */
13495    @ViewDebug.ExportedProperty(category = "drawing")
13496    public float getX() {
13497        return mLeft + getTranslationX();
13498    }
13499
13500    /**
13501     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
13502     * {@link #setTranslationX(float) translationX} property to be the difference between
13503     * the x value passed in and the current {@link #getLeft() left} property.
13504     *
13505     * @param x The visual x position of this view, in pixels.
13506     */
13507    public void setX(float x) {
13508        setTranslationX(x - mLeft);
13509    }
13510
13511    /**
13512     * The visual y position of this view, in pixels. This is equivalent to the
13513     * {@link #setTranslationY(float) translationY} property plus the current
13514     * {@link #getTop() top} property.
13515     *
13516     * @return The visual y position of this view, in pixels.
13517     */
13518    @ViewDebug.ExportedProperty(category = "drawing")
13519    public float getY() {
13520        return mTop + getTranslationY();
13521    }
13522
13523    /**
13524     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
13525     * {@link #setTranslationY(float) translationY} property to be the difference between
13526     * the y value passed in and the current {@link #getTop() top} property.
13527     *
13528     * @param y The visual y position of this view, in pixels.
13529     */
13530    public void setY(float y) {
13531        setTranslationY(y - mTop);
13532    }
13533
13534    /**
13535     * The visual z position of this view, in pixels. This is equivalent to the
13536     * {@link #setTranslationZ(float) translationZ} property plus the current
13537     * {@link #getElevation() elevation} property.
13538     *
13539     * @return The visual z position of this view, in pixels.
13540     */
13541    @ViewDebug.ExportedProperty(category = "drawing")
13542    public float getZ() {
13543        return getElevation() + getTranslationZ();
13544    }
13545
13546    /**
13547     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
13548     * {@link #setTranslationZ(float) translationZ} property to be the difference between
13549     * the x value passed in and the current {@link #getElevation() elevation} property.
13550     *
13551     * @param z The visual z position of this view, in pixels.
13552     */
13553    public void setZ(float z) {
13554        setTranslationZ(z - getElevation());
13555    }
13556
13557    /**
13558     * The base elevation of this view relative to its parent, in pixels.
13559     *
13560     * @return The base depth position of the view, in pixels.
13561     */
13562    @ViewDebug.ExportedProperty(category = "drawing")
13563    public float getElevation() {
13564        return mRenderNode.getElevation();
13565    }
13566
13567    /**
13568     * Sets the base elevation of this view, in pixels.
13569     *
13570     * @attr ref android.R.styleable#View_elevation
13571     */
13572    public void setElevation(float elevation) {
13573        if (elevation != getElevation()) {
13574            invalidateViewProperty(true, false);
13575            mRenderNode.setElevation(elevation);
13576            invalidateViewProperty(false, true);
13577
13578            invalidateParentIfNeededAndWasQuickRejected();
13579        }
13580    }
13581
13582    /**
13583     * The horizontal location of this view relative to its {@link #getLeft() left} position.
13584     * This position is post-layout, in addition to wherever the object's
13585     * layout placed it.
13586     *
13587     * @return The horizontal position of this view relative to its left position, in pixels.
13588     */
13589    @ViewDebug.ExportedProperty(category = "drawing")
13590    public float getTranslationX() {
13591        return mRenderNode.getTranslationX();
13592    }
13593
13594    /**
13595     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
13596     * This effectively positions the object post-layout, in addition to wherever the object's
13597     * layout placed it.
13598     *
13599     * @param translationX The horizontal position of this view relative to its left position,
13600     * in pixels.
13601     *
13602     * @attr ref android.R.styleable#View_translationX
13603     */
13604    public void setTranslationX(float translationX) {
13605        if (translationX != getTranslationX()) {
13606            invalidateViewProperty(true, false);
13607            mRenderNode.setTranslationX(translationX);
13608            invalidateViewProperty(false, true);
13609
13610            invalidateParentIfNeededAndWasQuickRejected();
13611            notifySubtreeAccessibilityStateChangedIfNeeded();
13612        }
13613    }
13614
13615    /**
13616     * The vertical location of this view relative to its {@link #getTop() top} position.
13617     * This position is post-layout, in addition to wherever the object's
13618     * layout placed it.
13619     *
13620     * @return The vertical position of this view relative to its top position,
13621     * in pixels.
13622     */
13623    @ViewDebug.ExportedProperty(category = "drawing")
13624    public float getTranslationY() {
13625        return mRenderNode.getTranslationY();
13626    }
13627
13628    /**
13629     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
13630     * This effectively positions the object post-layout, in addition to wherever the object's
13631     * layout placed it.
13632     *
13633     * @param translationY The vertical position of this view relative to its top position,
13634     * in pixels.
13635     *
13636     * @attr ref android.R.styleable#View_translationY
13637     */
13638    public void setTranslationY(float translationY) {
13639        if (translationY != getTranslationY()) {
13640            invalidateViewProperty(true, false);
13641            mRenderNode.setTranslationY(translationY);
13642            invalidateViewProperty(false, true);
13643
13644            invalidateParentIfNeededAndWasQuickRejected();
13645            notifySubtreeAccessibilityStateChangedIfNeeded();
13646        }
13647    }
13648
13649    /**
13650     * The depth location of this view relative to its {@link #getElevation() elevation}.
13651     *
13652     * @return The depth of this view relative to its elevation.
13653     */
13654    @ViewDebug.ExportedProperty(category = "drawing")
13655    public float getTranslationZ() {
13656        return mRenderNode.getTranslationZ();
13657    }
13658
13659    /**
13660     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
13661     *
13662     * @attr ref android.R.styleable#View_translationZ
13663     */
13664    public void setTranslationZ(float translationZ) {
13665        if (translationZ != getTranslationZ()) {
13666            invalidateViewProperty(true, false);
13667            mRenderNode.setTranslationZ(translationZ);
13668            invalidateViewProperty(false, true);
13669
13670            invalidateParentIfNeededAndWasQuickRejected();
13671        }
13672    }
13673
13674    /** @hide */
13675    public void setAnimationMatrix(Matrix matrix) {
13676        invalidateViewProperty(true, false);
13677        mRenderNode.setAnimationMatrix(matrix);
13678        invalidateViewProperty(false, true);
13679
13680        invalidateParentIfNeededAndWasQuickRejected();
13681    }
13682
13683    /**
13684     * Returns the current StateListAnimator if exists.
13685     *
13686     * @return StateListAnimator or null if it does not exists
13687     * @see    #setStateListAnimator(android.animation.StateListAnimator)
13688     */
13689    public StateListAnimator getStateListAnimator() {
13690        return mStateListAnimator;
13691    }
13692
13693    /**
13694     * Attaches the provided StateListAnimator to this View.
13695     * <p>
13696     * Any previously attached StateListAnimator will be detached.
13697     *
13698     * @param stateListAnimator The StateListAnimator to update the view
13699     * @see android.animation.StateListAnimator
13700     */
13701    public void setStateListAnimator(StateListAnimator stateListAnimator) {
13702        if (mStateListAnimator == stateListAnimator) {
13703            return;
13704        }
13705        if (mStateListAnimator != null) {
13706            mStateListAnimator.setTarget(null);
13707        }
13708        mStateListAnimator = stateListAnimator;
13709        if (stateListAnimator != null) {
13710            stateListAnimator.setTarget(this);
13711            if (isAttachedToWindow()) {
13712                stateListAnimator.setState(getDrawableState());
13713            }
13714        }
13715    }
13716
13717    /**
13718     * Returns whether the Outline should be used to clip the contents of the View.
13719     * <p>
13720     * Note that this flag will only be respected if the View's Outline returns true from
13721     * {@link Outline#canClip()}.
13722     *
13723     * @see #setOutlineProvider(ViewOutlineProvider)
13724     * @see #setClipToOutline(boolean)
13725     */
13726    public final boolean getClipToOutline() {
13727        return mRenderNode.getClipToOutline();
13728    }
13729
13730    /**
13731     * Sets whether the View's Outline should be used to clip the contents of the View.
13732     * <p>
13733     * Only a single non-rectangular clip can be applied on a View at any time.
13734     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
13735     * circular reveal} animation take priority over Outline clipping, and
13736     * child Outline clipping takes priority over Outline clipping done by a
13737     * parent.
13738     * <p>
13739     * Note that this flag will only be respected if the View's Outline returns true from
13740     * {@link Outline#canClip()}.
13741     *
13742     * @see #setOutlineProvider(ViewOutlineProvider)
13743     * @see #getClipToOutline()
13744     */
13745    public void setClipToOutline(boolean clipToOutline) {
13746        damageInParent();
13747        if (getClipToOutline() != clipToOutline) {
13748            mRenderNode.setClipToOutline(clipToOutline);
13749        }
13750    }
13751
13752    // correspond to the enum values of View_outlineProvider
13753    private static final int PROVIDER_BACKGROUND = 0;
13754    private static final int PROVIDER_NONE = 1;
13755    private static final int PROVIDER_BOUNDS = 2;
13756    private static final int PROVIDER_PADDED_BOUNDS = 3;
13757    private void setOutlineProviderFromAttribute(int providerInt) {
13758        switch (providerInt) {
13759            case PROVIDER_BACKGROUND:
13760                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
13761                break;
13762            case PROVIDER_NONE:
13763                setOutlineProvider(null);
13764                break;
13765            case PROVIDER_BOUNDS:
13766                setOutlineProvider(ViewOutlineProvider.BOUNDS);
13767                break;
13768            case PROVIDER_PADDED_BOUNDS:
13769                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
13770                break;
13771        }
13772    }
13773
13774    /**
13775     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
13776     * the shape of the shadow it casts, and enables outline clipping.
13777     * <p>
13778     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
13779     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
13780     * outline provider with this method allows this behavior to be overridden.
13781     * <p>
13782     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
13783     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
13784     * <p>
13785     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
13786     *
13787     * @see #setClipToOutline(boolean)
13788     * @see #getClipToOutline()
13789     * @see #getOutlineProvider()
13790     */
13791    public void setOutlineProvider(ViewOutlineProvider provider) {
13792        mOutlineProvider = provider;
13793        invalidateOutline();
13794    }
13795
13796    /**
13797     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
13798     * that defines the shape of the shadow it casts, and enables outline clipping.
13799     *
13800     * @see #setOutlineProvider(ViewOutlineProvider)
13801     */
13802    public ViewOutlineProvider getOutlineProvider() {
13803        return mOutlineProvider;
13804    }
13805
13806    /**
13807     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
13808     *
13809     * @see #setOutlineProvider(ViewOutlineProvider)
13810     */
13811    public void invalidateOutline() {
13812        rebuildOutline();
13813
13814        notifySubtreeAccessibilityStateChangedIfNeeded();
13815        invalidateViewProperty(false, false);
13816    }
13817
13818    /**
13819     * Internal version of {@link #invalidateOutline()} which invalidates the
13820     * outline without invalidating the view itself. This is intended to be called from
13821     * within methods in the View class itself which are the result of the view being
13822     * invalidated already. For example, when we are drawing the background of a View,
13823     * we invalidate the outline in case it changed in the meantime, but we do not
13824     * need to invalidate the view because we're already drawing the background as part
13825     * of drawing the view in response to an earlier invalidation of the view.
13826     */
13827    private void rebuildOutline() {
13828        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
13829        if (mAttachInfo == null) return;
13830
13831        if (mOutlineProvider == null) {
13832            // no provider, remove outline
13833            mRenderNode.setOutline(null);
13834        } else {
13835            final Outline outline = mAttachInfo.mTmpOutline;
13836            outline.setEmpty();
13837            outline.setAlpha(1.0f);
13838
13839            mOutlineProvider.getOutline(this, outline);
13840            mRenderNode.setOutline(outline);
13841        }
13842    }
13843
13844    /**
13845     * HierarchyViewer only
13846     *
13847     * @hide
13848     */
13849    @ViewDebug.ExportedProperty(category = "drawing")
13850    public boolean hasShadow() {
13851        return mRenderNode.hasShadow();
13852    }
13853
13854
13855    /** @hide */
13856    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
13857        mRenderNode.setRevealClip(shouldClip, x, y, radius);
13858        invalidateViewProperty(false, false);
13859    }
13860
13861    /**
13862     * Hit rectangle in parent's coordinates
13863     *
13864     * @param outRect The hit rectangle of the view.
13865     */
13866    public void getHitRect(Rect outRect) {
13867        if (hasIdentityMatrix() || mAttachInfo == null) {
13868            outRect.set(mLeft, mTop, mRight, mBottom);
13869        } else {
13870            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
13871            tmpRect.set(0, 0, getWidth(), getHeight());
13872            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
13873            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
13874                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
13875        }
13876    }
13877
13878    /**
13879     * Determines whether the given point, in local coordinates is inside the view.
13880     */
13881    /*package*/ final boolean pointInView(float localX, float localY) {
13882        return pointInView(localX, localY, 0);
13883    }
13884
13885    /**
13886     * Utility method to determine whether the given point, in local coordinates,
13887     * is inside the view, where the area of the view is expanded by the slop factor.
13888     * This method is called while processing touch-move events to determine if the event
13889     * is still within the view.
13890     *
13891     * @hide
13892     */
13893    public boolean pointInView(float localX, float localY, float slop) {
13894        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
13895                localY < ((mBottom - mTop) + slop);
13896    }
13897
13898    /**
13899     * When a view has focus and the user navigates away from it, the next view is searched for
13900     * starting from the rectangle filled in by this method.
13901     *
13902     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
13903     * of the view.  However, if your view maintains some idea of internal selection,
13904     * such as a cursor, or a selected row or column, you should override this method and
13905     * fill in a more specific rectangle.
13906     *
13907     * @param r The rectangle to fill in, in this view's coordinates.
13908     */
13909    public void getFocusedRect(Rect r) {
13910        getDrawingRect(r);
13911    }
13912
13913    /**
13914     * If some part of this view is not clipped by any of its parents, then
13915     * return that area in r in global (root) coordinates. To convert r to local
13916     * coordinates (without taking possible View rotations into account), offset
13917     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
13918     * If the view is completely clipped or translated out, return false.
13919     *
13920     * @param r If true is returned, r holds the global coordinates of the
13921     *        visible portion of this view.
13922     * @param globalOffset If true is returned, globalOffset holds the dx,dy
13923     *        between this view and its root. globalOffet may be null.
13924     * @return true if r is non-empty (i.e. part of the view is visible at the
13925     *         root level.
13926     */
13927    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
13928        int width = mRight - mLeft;
13929        int height = mBottom - mTop;
13930        if (width > 0 && height > 0) {
13931            r.set(0, 0, width, height);
13932            if (globalOffset != null) {
13933                globalOffset.set(-mScrollX, -mScrollY);
13934            }
13935            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
13936        }
13937        return false;
13938    }
13939
13940    public final boolean getGlobalVisibleRect(Rect r) {
13941        return getGlobalVisibleRect(r, null);
13942    }
13943
13944    public final boolean getLocalVisibleRect(Rect r) {
13945        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
13946        if (getGlobalVisibleRect(r, offset)) {
13947            r.offset(-offset.x, -offset.y); // make r local
13948            return true;
13949        }
13950        return false;
13951    }
13952
13953    /**
13954     * Offset this view's vertical location by the specified number of pixels.
13955     *
13956     * @param offset the number of pixels to offset the view by
13957     */
13958    public void offsetTopAndBottom(int offset) {
13959        if (offset != 0) {
13960            final boolean matrixIsIdentity = hasIdentityMatrix();
13961            if (matrixIsIdentity) {
13962                if (isHardwareAccelerated()) {
13963                    invalidateViewProperty(false, false);
13964                } else {
13965                    final ViewParent p = mParent;
13966                    if (p != null && mAttachInfo != null) {
13967                        final Rect r = mAttachInfo.mTmpInvalRect;
13968                        int minTop;
13969                        int maxBottom;
13970                        int yLoc;
13971                        if (offset < 0) {
13972                            minTop = mTop + offset;
13973                            maxBottom = mBottom;
13974                            yLoc = offset;
13975                        } else {
13976                            minTop = mTop;
13977                            maxBottom = mBottom + offset;
13978                            yLoc = 0;
13979                        }
13980                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
13981                        p.invalidateChild(this, r);
13982                    }
13983                }
13984            } else {
13985                invalidateViewProperty(false, false);
13986            }
13987
13988            mTop += offset;
13989            mBottom += offset;
13990            mRenderNode.offsetTopAndBottom(offset);
13991            if (isHardwareAccelerated()) {
13992                invalidateViewProperty(false, false);
13993                invalidateParentIfNeededAndWasQuickRejected();
13994            } else {
13995                if (!matrixIsIdentity) {
13996                    invalidateViewProperty(false, true);
13997                }
13998                invalidateParentIfNeeded();
13999            }
14000            notifySubtreeAccessibilityStateChangedIfNeeded();
14001        }
14002    }
14003
14004    /**
14005     * Offset this view's horizontal location by the specified amount of pixels.
14006     *
14007     * @param offset the number of pixels to offset the view by
14008     */
14009    public void offsetLeftAndRight(int offset) {
14010        if (offset != 0) {
14011            final boolean matrixIsIdentity = hasIdentityMatrix();
14012            if (matrixIsIdentity) {
14013                if (isHardwareAccelerated()) {
14014                    invalidateViewProperty(false, false);
14015                } else {
14016                    final ViewParent p = mParent;
14017                    if (p != null && mAttachInfo != null) {
14018                        final Rect r = mAttachInfo.mTmpInvalRect;
14019                        int minLeft;
14020                        int maxRight;
14021                        if (offset < 0) {
14022                            minLeft = mLeft + offset;
14023                            maxRight = mRight;
14024                        } else {
14025                            minLeft = mLeft;
14026                            maxRight = mRight + offset;
14027                        }
14028                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
14029                        p.invalidateChild(this, r);
14030                    }
14031                }
14032            } else {
14033                invalidateViewProperty(false, false);
14034            }
14035
14036            mLeft += offset;
14037            mRight += offset;
14038            mRenderNode.offsetLeftAndRight(offset);
14039            if (isHardwareAccelerated()) {
14040                invalidateViewProperty(false, false);
14041                invalidateParentIfNeededAndWasQuickRejected();
14042            } else {
14043                if (!matrixIsIdentity) {
14044                    invalidateViewProperty(false, true);
14045                }
14046                invalidateParentIfNeeded();
14047            }
14048            notifySubtreeAccessibilityStateChangedIfNeeded();
14049        }
14050    }
14051
14052    /**
14053     * Get the LayoutParams associated with this view. All views should have
14054     * layout parameters. These supply parameters to the <i>parent</i> of this
14055     * view specifying how it should be arranged. There are many subclasses of
14056     * ViewGroup.LayoutParams, and these correspond to the different subclasses
14057     * of ViewGroup that are responsible for arranging their children.
14058     *
14059     * This method may return null if this View is not attached to a parent
14060     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
14061     * was not invoked successfully. When a View is attached to a parent
14062     * ViewGroup, this method must not return null.
14063     *
14064     * @return The LayoutParams associated with this view, or null if no
14065     *         parameters have been set yet
14066     */
14067    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
14068    public ViewGroup.LayoutParams getLayoutParams() {
14069        return mLayoutParams;
14070    }
14071
14072    /**
14073     * Set the layout parameters associated with this view. These supply
14074     * parameters to the <i>parent</i> of this view specifying how it should be
14075     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
14076     * correspond to the different subclasses of ViewGroup that are responsible
14077     * for arranging their children.
14078     *
14079     * @param params The layout parameters for this view, cannot be null
14080     */
14081    public void setLayoutParams(ViewGroup.LayoutParams params) {
14082        if (params == null) {
14083            throw new NullPointerException("Layout parameters cannot be null");
14084        }
14085        mLayoutParams = params;
14086        resolveLayoutParams();
14087        if (mParent instanceof ViewGroup) {
14088            ((ViewGroup) mParent).onSetLayoutParams(this, params);
14089        }
14090        requestLayout();
14091    }
14092
14093    /**
14094     * Resolve the layout parameters depending on the resolved layout direction
14095     *
14096     * @hide
14097     */
14098    public void resolveLayoutParams() {
14099        if (mLayoutParams != null) {
14100            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
14101        }
14102    }
14103
14104    /**
14105     * Set the scrolled position of your view. This will cause a call to
14106     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14107     * invalidated.
14108     * @param x the x position to scroll to
14109     * @param y the y position to scroll to
14110     */
14111    public void scrollTo(int x, int y) {
14112        if (mScrollX != x || mScrollY != y) {
14113            int oldX = mScrollX;
14114            int oldY = mScrollY;
14115            mScrollX = x;
14116            mScrollY = y;
14117            invalidateParentCaches();
14118            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
14119            if (!awakenScrollBars()) {
14120                postInvalidateOnAnimation();
14121            }
14122        }
14123    }
14124
14125    /**
14126     * Move the scrolled position of your view. This will cause a call to
14127     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14128     * invalidated.
14129     * @param x the amount of pixels to scroll by horizontally
14130     * @param y the amount of pixels to scroll by vertically
14131     */
14132    public void scrollBy(int x, int y) {
14133        scrollTo(mScrollX + x, mScrollY + y);
14134    }
14135
14136    /**
14137     * <p>Trigger the scrollbars to draw. When invoked this method starts an
14138     * animation to fade the scrollbars out after a default delay. If a subclass
14139     * provides animated scrolling, the start delay should equal the duration
14140     * of the scrolling animation.</p>
14141     *
14142     * <p>The animation starts only if at least one of the scrollbars is
14143     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
14144     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14145     * this method returns true, and false otherwise. If the animation is
14146     * started, this method calls {@link #invalidate()}; in that case the
14147     * caller should not call {@link #invalidate()}.</p>
14148     *
14149     * <p>This method should be invoked every time a subclass directly updates
14150     * the scroll parameters.</p>
14151     *
14152     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
14153     * and {@link #scrollTo(int, int)}.</p>
14154     *
14155     * @return true if the animation is played, false otherwise
14156     *
14157     * @see #awakenScrollBars(int)
14158     * @see #scrollBy(int, int)
14159     * @see #scrollTo(int, int)
14160     * @see #isHorizontalScrollBarEnabled()
14161     * @see #isVerticalScrollBarEnabled()
14162     * @see #setHorizontalScrollBarEnabled(boolean)
14163     * @see #setVerticalScrollBarEnabled(boolean)
14164     */
14165    protected boolean awakenScrollBars() {
14166        return mScrollCache != null &&
14167                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
14168    }
14169
14170    /**
14171     * Trigger the scrollbars to draw.
14172     * This method differs from awakenScrollBars() only in its default duration.
14173     * initialAwakenScrollBars() will show the scroll bars for longer than
14174     * usual to give the user more of a chance to notice them.
14175     *
14176     * @return true if the animation is played, false otherwise.
14177     */
14178    private boolean initialAwakenScrollBars() {
14179        return mScrollCache != null &&
14180                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
14181    }
14182
14183    /**
14184     * <p>
14185     * Trigger the scrollbars to draw. When invoked this method starts an
14186     * animation to fade the scrollbars out after a fixed delay. If a subclass
14187     * provides animated scrolling, the start delay should equal the duration of
14188     * the scrolling animation.
14189     * </p>
14190     *
14191     * <p>
14192     * The animation starts only if at least one of the scrollbars is enabled,
14193     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14194     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14195     * this method returns true, and false otherwise. If the animation is
14196     * started, this method calls {@link #invalidate()}; in that case the caller
14197     * should not call {@link #invalidate()}.
14198     * </p>
14199     *
14200     * <p>
14201     * This method should be invoked every time a subclass directly updates the
14202     * scroll parameters.
14203     * </p>
14204     *
14205     * @param startDelay the delay, in milliseconds, after which the animation
14206     *        should start; when the delay is 0, the animation starts
14207     *        immediately
14208     * @return true if the animation is played, false otherwise
14209     *
14210     * @see #scrollBy(int, int)
14211     * @see #scrollTo(int, int)
14212     * @see #isHorizontalScrollBarEnabled()
14213     * @see #isVerticalScrollBarEnabled()
14214     * @see #setHorizontalScrollBarEnabled(boolean)
14215     * @see #setVerticalScrollBarEnabled(boolean)
14216     */
14217    protected boolean awakenScrollBars(int startDelay) {
14218        return awakenScrollBars(startDelay, true);
14219    }
14220
14221    /**
14222     * <p>
14223     * Trigger the scrollbars to draw. When invoked this method starts an
14224     * animation to fade the scrollbars out after a fixed delay. If a subclass
14225     * provides animated scrolling, the start delay should equal the duration of
14226     * the scrolling animation.
14227     * </p>
14228     *
14229     * <p>
14230     * The animation starts only if at least one of the scrollbars is enabled,
14231     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14232     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14233     * this method returns true, and false otherwise. If the animation is
14234     * started, this method calls {@link #invalidate()} if the invalidate parameter
14235     * is set to true; in that case the caller
14236     * should not call {@link #invalidate()}.
14237     * </p>
14238     *
14239     * <p>
14240     * This method should be invoked every time a subclass directly updates the
14241     * scroll parameters.
14242     * </p>
14243     *
14244     * @param startDelay the delay, in milliseconds, after which the animation
14245     *        should start; when the delay is 0, the animation starts
14246     *        immediately
14247     *
14248     * @param invalidate Whether this method should call invalidate
14249     *
14250     * @return true if the animation is played, false otherwise
14251     *
14252     * @see #scrollBy(int, int)
14253     * @see #scrollTo(int, int)
14254     * @see #isHorizontalScrollBarEnabled()
14255     * @see #isVerticalScrollBarEnabled()
14256     * @see #setHorizontalScrollBarEnabled(boolean)
14257     * @see #setVerticalScrollBarEnabled(boolean)
14258     */
14259    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
14260        final ScrollabilityCache scrollCache = mScrollCache;
14261
14262        if (scrollCache == null || !scrollCache.fadeScrollBars) {
14263            return false;
14264        }
14265
14266        if (scrollCache.scrollBar == null) {
14267            scrollCache.scrollBar = new ScrollBarDrawable();
14268            scrollCache.scrollBar.setState(getDrawableState());
14269            scrollCache.scrollBar.setCallback(this);
14270        }
14271
14272        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
14273
14274            if (invalidate) {
14275                // Invalidate to show the scrollbars
14276                postInvalidateOnAnimation();
14277            }
14278
14279            if (scrollCache.state == ScrollabilityCache.OFF) {
14280                // FIXME: this is copied from WindowManagerService.
14281                // We should get this value from the system when it
14282                // is possible to do so.
14283                final int KEY_REPEAT_FIRST_DELAY = 750;
14284                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
14285            }
14286
14287            // Tell mScrollCache when we should start fading. This may
14288            // extend the fade start time if one was already scheduled
14289            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
14290            scrollCache.fadeStartTime = fadeStartTime;
14291            scrollCache.state = ScrollabilityCache.ON;
14292
14293            // Schedule our fader to run, unscheduling any old ones first
14294            if (mAttachInfo != null) {
14295                mAttachInfo.mHandler.removeCallbacks(scrollCache);
14296                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
14297            }
14298
14299            return true;
14300        }
14301
14302        return false;
14303    }
14304
14305    /**
14306     * Do not invalidate views which are not visible and which are not running an animation. They
14307     * will not get drawn and they should not set dirty flags as if they will be drawn
14308     */
14309    private boolean skipInvalidate() {
14310        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
14311                (!(mParent instanceof ViewGroup) ||
14312                        !((ViewGroup) mParent).isViewTransitioning(this));
14313    }
14314
14315    /**
14316     * Mark the area defined by dirty as needing to be drawn. If the view is
14317     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14318     * point in the future.
14319     * <p>
14320     * This must be called from a UI thread. To call from a non-UI thread, call
14321     * {@link #postInvalidate()}.
14322     * <p>
14323     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
14324     * {@code dirty}.
14325     *
14326     * @param dirty the rectangle representing the bounds of the dirty region
14327     */
14328    public void invalidate(Rect dirty) {
14329        final int scrollX = mScrollX;
14330        final int scrollY = mScrollY;
14331        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
14332                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
14333    }
14334
14335    /**
14336     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
14337     * coordinates of the dirty rect are relative to the view. If the view is
14338     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14339     * point in the future.
14340     * <p>
14341     * This must be called from a UI thread. To call from a non-UI thread, call
14342     * {@link #postInvalidate()}.
14343     *
14344     * @param l the left position of the dirty region
14345     * @param t the top position of the dirty region
14346     * @param r the right position of the dirty region
14347     * @param b the bottom position of the dirty region
14348     */
14349    public void invalidate(int l, int t, int r, int b) {
14350        final int scrollX = mScrollX;
14351        final int scrollY = mScrollY;
14352        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
14353    }
14354
14355    /**
14356     * Invalidate the whole view. If the view is visible,
14357     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
14358     * the future.
14359     * <p>
14360     * This must be called from a UI thread. To call from a non-UI thread, call
14361     * {@link #postInvalidate()}.
14362     */
14363    public void invalidate() {
14364        invalidate(true);
14365    }
14366
14367    /**
14368     * This is where the invalidate() work actually happens. A full invalidate()
14369     * causes the drawing cache to be invalidated, but this function can be
14370     * called with invalidateCache set to false to skip that invalidation step
14371     * for cases that do not need it (for example, a component that remains at
14372     * the same dimensions with the same content).
14373     *
14374     * @param invalidateCache Whether the drawing cache for this view should be
14375     *            invalidated as well. This is usually true for a full
14376     *            invalidate, but may be set to false if the View's contents or
14377     *            dimensions have not changed.
14378     * @hide
14379     */
14380    public void invalidate(boolean invalidateCache) {
14381        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
14382    }
14383
14384    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
14385            boolean fullInvalidate) {
14386        if (mGhostView != null) {
14387            mGhostView.invalidate(true);
14388            return;
14389        }
14390
14391        if (skipInvalidate()) {
14392            return;
14393        }
14394
14395        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
14396                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
14397                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
14398                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
14399            if (fullInvalidate) {
14400                mLastIsOpaque = isOpaque();
14401                mPrivateFlags &= ~PFLAG_DRAWN;
14402            }
14403
14404            mPrivateFlags |= PFLAG_DIRTY;
14405
14406            if (invalidateCache) {
14407                mPrivateFlags |= PFLAG_INVALIDATED;
14408                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14409            }
14410
14411            // Propagate the damage rectangle to the parent view.
14412            final AttachInfo ai = mAttachInfo;
14413            final ViewParent p = mParent;
14414            if (p != null && ai != null && l < r && t < b) {
14415                final Rect damage = ai.mTmpInvalRect;
14416                damage.set(l, t, r, b);
14417                p.invalidateChild(this, damage);
14418            }
14419
14420            // Damage the entire projection receiver, if necessary.
14421            if (mBackground != null && mBackground.isProjected()) {
14422                final View receiver = getProjectionReceiver();
14423                if (receiver != null) {
14424                    receiver.damageInParent();
14425                }
14426            }
14427        }
14428    }
14429
14430    /**
14431     * @return this view's projection receiver, or {@code null} if none exists
14432     */
14433    private View getProjectionReceiver() {
14434        ViewParent p = getParent();
14435        while (p != null && p instanceof View) {
14436            final View v = (View) p;
14437            if (v.isProjectionReceiver()) {
14438                return v;
14439            }
14440            p = p.getParent();
14441        }
14442
14443        return null;
14444    }
14445
14446    /**
14447     * @return whether the view is a projection receiver
14448     */
14449    private boolean isProjectionReceiver() {
14450        return mBackground != null;
14451    }
14452
14453    /**
14454     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
14455     * set any flags or handle all of the cases handled by the default invalidation methods.
14456     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
14457     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
14458     * walk up the hierarchy, transforming the dirty rect as necessary.
14459     *
14460     * The method also handles normal invalidation logic if display list properties are not
14461     * being used in this view. The invalidateParent and forceRedraw flags are used by that
14462     * backup approach, to handle these cases used in the various property-setting methods.
14463     *
14464     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
14465     * are not being used in this view
14466     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
14467     * list properties are not being used in this view
14468     */
14469    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
14470        if (!isHardwareAccelerated()
14471                || !mRenderNode.isValid()
14472                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
14473            if (invalidateParent) {
14474                invalidateParentCaches();
14475            }
14476            if (forceRedraw) {
14477                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14478            }
14479            invalidate(false);
14480        } else {
14481            damageInParent();
14482        }
14483    }
14484
14485    /**
14486     * Tells the parent view to damage this view's bounds.
14487     *
14488     * @hide
14489     */
14490    protected void damageInParent() {
14491        if (mParent != null && mAttachInfo != null) {
14492            mParent.onDescendantInvalidated(this, this);
14493        }
14494    }
14495
14496    /**
14497     * Utility method to transform a given Rect by the current matrix of this view.
14498     */
14499    void transformRect(final Rect rect) {
14500        if (!getMatrix().isIdentity()) {
14501            RectF boundingRect = mAttachInfo.mTmpTransformRect;
14502            boundingRect.set(rect);
14503            getMatrix().mapRect(boundingRect);
14504            rect.set((int) Math.floor(boundingRect.left),
14505                    (int) Math.floor(boundingRect.top),
14506                    (int) Math.ceil(boundingRect.right),
14507                    (int) Math.ceil(boundingRect.bottom));
14508        }
14509    }
14510
14511    /**
14512     * Used to indicate that the parent of this view should clear its caches. This functionality
14513     * is used to force the parent to rebuild its display list (when hardware-accelerated),
14514     * which is necessary when various parent-managed properties of the view change, such as
14515     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
14516     * clears the parent caches and does not causes an invalidate event.
14517     *
14518     * @hide
14519     */
14520    protected void invalidateParentCaches() {
14521        if (mParent instanceof View) {
14522            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
14523        }
14524    }
14525
14526    /**
14527     * Used to indicate that the parent of this view should be invalidated. This functionality
14528     * is used to force the parent to rebuild its display list (when hardware-accelerated),
14529     * which is necessary when various parent-managed properties of the view change, such as
14530     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
14531     * an invalidation event to the parent.
14532     *
14533     * @hide
14534     */
14535    protected void invalidateParentIfNeeded() {
14536        if (isHardwareAccelerated() && mParent instanceof View) {
14537            ((View) mParent).invalidate(true);
14538        }
14539    }
14540
14541    /**
14542     * @hide
14543     */
14544    protected void invalidateParentIfNeededAndWasQuickRejected() {
14545        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
14546            // View was rejected last time it was drawn by its parent; this may have changed
14547            invalidateParentIfNeeded();
14548        }
14549    }
14550
14551    /**
14552     * Indicates whether this View is opaque. An opaque View guarantees that it will
14553     * draw all the pixels overlapping its bounds using a fully opaque color.
14554     *
14555     * Subclasses of View should override this method whenever possible to indicate
14556     * whether an instance is opaque. Opaque Views are treated in a special way by
14557     * the View hierarchy, possibly allowing it to perform optimizations during
14558     * invalidate/draw passes.
14559     *
14560     * @return True if this View is guaranteed to be fully opaque, false otherwise.
14561     */
14562    @ViewDebug.ExportedProperty(category = "drawing")
14563    public boolean isOpaque() {
14564        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
14565                getFinalAlpha() >= 1.0f;
14566    }
14567
14568    /**
14569     * @hide
14570     */
14571    protected void computeOpaqueFlags() {
14572        // Opaque if:
14573        //   - Has a background
14574        //   - Background is opaque
14575        //   - Doesn't have scrollbars or scrollbars overlay
14576
14577        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
14578            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
14579        } else {
14580            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
14581        }
14582
14583        final int flags = mViewFlags;
14584        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
14585                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
14586                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
14587            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
14588        } else {
14589            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
14590        }
14591    }
14592
14593    /**
14594     * @hide
14595     */
14596    protected boolean hasOpaqueScrollbars() {
14597        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
14598    }
14599
14600    /**
14601     * @return A handler associated with the thread running the View. This
14602     * handler can be used to pump events in the UI events queue.
14603     */
14604    public Handler getHandler() {
14605        final AttachInfo attachInfo = mAttachInfo;
14606        if (attachInfo != null) {
14607            return attachInfo.mHandler;
14608        }
14609        return null;
14610    }
14611
14612    /**
14613     * Returns the queue of runnable for this view.
14614     *
14615     * @return the queue of runnables for this view
14616     */
14617    private HandlerActionQueue getRunQueue() {
14618        if (mRunQueue == null) {
14619            mRunQueue = new HandlerActionQueue();
14620        }
14621        return mRunQueue;
14622    }
14623
14624    /**
14625     * Gets the view root associated with the View.
14626     * @return The view root, or null if none.
14627     * @hide
14628     */
14629    public ViewRootImpl getViewRootImpl() {
14630        if (mAttachInfo != null) {
14631            return mAttachInfo.mViewRootImpl;
14632        }
14633        return null;
14634    }
14635
14636    /**
14637     * @hide
14638     */
14639    public ThreadedRenderer getThreadedRenderer() {
14640        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
14641    }
14642
14643    /**
14644     * <p>Causes the Runnable to be added to the message queue.
14645     * The runnable will be run on the user interface thread.</p>
14646     *
14647     * @param action The Runnable that will be executed.
14648     *
14649     * @return Returns true if the Runnable was successfully placed in to the
14650     *         message queue.  Returns false on failure, usually because the
14651     *         looper processing the message queue is exiting.
14652     *
14653     * @see #postDelayed
14654     * @see #removeCallbacks
14655     */
14656    public boolean post(Runnable action) {
14657        final AttachInfo attachInfo = mAttachInfo;
14658        if (attachInfo != null) {
14659            return attachInfo.mHandler.post(action);
14660        }
14661
14662        // Postpone the runnable until we know on which thread it needs to run.
14663        // Assume that the runnable will be successfully placed after attach.
14664        getRunQueue().post(action);
14665        return true;
14666    }
14667
14668    /**
14669     * <p>Causes the Runnable to be added to the message queue, to be run
14670     * after the specified amount of time elapses.
14671     * The runnable will be run on the user interface thread.</p>
14672     *
14673     * @param action The Runnable that will be executed.
14674     * @param delayMillis The delay (in milliseconds) until the Runnable
14675     *        will be executed.
14676     *
14677     * @return true if the Runnable was successfully placed in to the
14678     *         message queue.  Returns false on failure, usually because the
14679     *         looper processing the message queue is exiting.  Note that a
14680     *         result of true does not mean the Runnable will be processed --
14681     *         if the looper is quit before the delivery time of the message
14682     *         occurs then the message will be dropped.
14683     *
14684     * @see #post
14685     * @see #removeCallbacks
14686     */
14687    public boolean postDelayed(Runnable action, long delayMillis) {
14688        final AttachInfo attachInfo = mAttachInfo;
14689        if (attachInfo != null) {
14690            return attachInfo.mHandler.postDelayed(action, delayMillis);
14691        }
14692
14693        // Postpone the runnable until we know on which thread it needs to run.
14694        // Assume that the runnable will be successfully placed after attach.
14695        getRunQueue().postDelayed(action, delayMillis);
14696        return true;
14697    }
14698
14699    /**
14700     * <p>Causes the Runnable to execute on the next animation time step.
14701     * The runnable will be run on the user interface thread.</p>
14702     *
14703     * @param action The Runnable that will be executed.
14704     *
14705     * @see #postOnAnimationDelayed
14706     * @see #removeCallbacks
14707     */
14708    public void postOnAnimation(Runnable action) {
14709        final AttachInfo attachInfo = mAttachInfo;
14710        if (attachInfo != null) {
14711            attachInfo.mViewRootImpl.mChoreographer.postCallback(
14712                    Choreographer.CALLBACK_ANIMATION, action, null);
14713        } else {
14714            // Postpone the runnable until we know
14715            // on which thread it needs to run.
14716            getRunQueue().post(action);
14717        }
14718    }
14719
14720    /**
14721     * <p>Causes the Runnable to execute on the next animation time step,
14722     * after the specified amount of time elapses.
14723     * The runnable will be run on the user interface thread.</p>
14724     *
14725     * @param action The Runnable that will be executed.
14726     * @param delayMillis The delay (in milliseconds) until the Runnable
14727     *        will be executed.
14728     *
14729     * @see #postOnAnimation
14730     * @see #removeCallbacks
14731     */
14732    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
14733        final AttachInfo attachInfo = mAttachInfo;
14734        if (attachInfo != null) {
14735            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
14736                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
14737        } else {
14738            // Postpone the runnable until we know
14739            // on which thread it needs to run.
14740            getRunQueue().postDelayed(action, delayMillis);
14741        }
14742    }
14743
14744    /**
14745     * <p>Removes the specified Runnable from the message queue.</p>
14746     *
14747     * @param action The Runnable to remove from the message handling queue
14748     *
14749     * @return true if this view could ask the Handler to remove the Runnable,
14750     *         false otherwise. When the returned value is true, the Runnable
14751     *         may or may not have been actually removed from the message queue
14752     *         (for instance, if the Runnable was not in the queue already.)
14753     *
14754     * @see #post
14755     * @see #postDelayed
14756     * @see #postOnAnimation
14757     * @see #postOnAnimationDelayed
14758     */
14759    public boolean removeCallbacks(Runnable action) {
14760        if (action != null) {
14761            final AttachInfo attachInfo = mAttachInfo;
14762            if (attachInfo != null) {
14763                attachInfo.mHandler.removeCallbacks(action);
14764                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14765                        Choreographer.CALLBACK_ANIMATION, action, null);
14766            }
14767            getRunQueue().removeCallbacks(action);
14768        }
14769        return true;
14770    }
14771
14772    /**
14773     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
14774     * Use this to invalidate the View from a non-UI thread.</p>
14775     *
14776     * <p>This method can be invoked from outside of the UI thread
14777     * only when this View is attached to a window.</p>
14778     *
14779     * @see #invalidate()
14780     * @see #postInvalidateDelayed(long)
14781     */
14782    public void postInvalidate() {
14783        postInvalidateDelayed(0);
14784    }
14785
14786    /**
14787     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14788     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
14789     *
14790     * <p>This method can be invoked from outside of the UI thread
14791     * only when this View is attached to a window.</p>
14792     *
14793     * @param left The left coordinate of the rectangle to invalidate.
14794     * @param top The top coordinate of the rectangle to invalidate.
14795     * @param right The right coordinate of the rectangle to invalidate.
14796     * @param bottom The bottom coordinate of the rectangle to invalidate.
14797     *
14798     * @see #invalidate(int, int, int, int)
14799     * @see #invalidate(Rect)
14800     * @see #postInvalidateDelayed(long, int, int, int, int)
14801     */
14802    public void postInvalidate(int left, int top, int right, int bottom) {
14803        postInvalidateDelayed(0, left, top, right, bottom);
14804    }
14805
14806    /**
14807     * <p>Cause an invalidate to happen on a subsequent cycle through the event
14808     * loop. Waits for the specified amount of time.</p>
14809     *
14810     * <p>This method can be invoked from outside of the UI thread
14811     * only when this View is attached to a window.</p>
14812     *
14813     * @param delayMilliseconds the duration in milliseconds to delay the
14814     *         invalidation by
14815     *
14816     * @see #invalidate()
14817     * @see #postInvalidate()
14818     */
14819    public void postInvalidateDelayed(long delayMilliseconds) {
14820        // We try only with the AttachInfo because there's no point in invalidating
14821        // if we are not attached to our window
14822        final AttachInfo attachInfo = mAttachInfo;
14823        if (attachInfo != null) {
14824            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
14825        }
14826    }
14827
14828    /**
14829     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
14830     * through the event loop. Waits for the specified amount of time.</p>
14831     *
14832     * <p>This method can be invoked from outside of the UI thread
14833     * only when this View is attached to a window.</p>
14834     *
14835     * @param delayMilliseconds the duration in milliseconds to delay the
14836     *         invalidation by
14837     * @param left The left coordinate of the rectangle to invalidate.
14838     * @param top The top coordinate of the rectangle to invalidate.
14839     * @param right The right coordinate of the rectangle to invalidate.
14840     * @param bottom The bottom coordinate of the rectangle to invalidate.
14841     *
14842     * @see #invalidate(int, int, int, int)
14843     * @see #invalidate(Rect)
14844     * @see #postInvalidate(int, int, int, int)
14845     */
14846    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
14847            int right, int bottom) {
14848
14849        // We try only with the AttachInfo because there's no point in invalidating
14850        // if we are not attached to our window
14851        final AttachInfo attachInfo = mAttachInfo;
14852        if (attachInfo != null) {
14853            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14854            info.target = this;
14855            info.left = left;
14856            info.top = top;
14857            info.right = right;
14858            info.bottom = bottom;
14859
14860            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
14861        }
14862    }
14863
14864    /**
14865     * <p>Cause an invalidate to happen on the next animation time step, typically the
14866     * next display frame.</p>
14867     *
14868     * <p>This method can be invoked from outside of the UI thread
14869     * only when this View is attached to a window.</p>
14870     *
14871     * @see #invalidate()
14872     */
14873    public void postInvalidateOnAnimation() {
14874        // We try only with the AttachInfo because there's no point in invalidating
14875        // if we are not attached to our window
14876        final AttachInfo attachInfo = mAttachInfo;
14877        if (attachInfo != null) {
14878            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
14879        }
14880    }
14881
14882    /**
14883     * <p>Cause an invalidate of the specified area to happen on the next animation
14884     * time step, typically the next display frame.</p>
14885     *
14886     * <p>This method can be invoked from outside of the UI thread
14887     * only when this View is attached to a window.</p>
14888     *
14889     * @param left The left coordinate of the rectangle to invalidate.
14890     * @param top The top coordinate of the rectangle to invalidate.
14891     * @param right The right coordinate of the rectangle to invalidate.
14892     * @param bottom The bottom coordinate of the rectangle to invalidate.
14893     *
14894     * @see #invalidate(int, int, int, int)
14895     * @see #invalidate(Rect)
14896     */
14897    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
14898        // We try only with the AttachInfo because there's no point in invalidating
14899        // if we are not attached to our window
14900        final AttachInfo attachInfo = mAttachInfo;
14901        if (attachInfo != null) {
14902            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
14903            info.target = this;
14904            info.left = left;
14905            info.top = top;
14906            info.right = right;
14907            info.bottom = bottom;
14908
14909            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
14910        }
14911    }
14912
14913    /**
14914     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
14915     * This event is sent at most once every
14916     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
14917     */
14918    private void postSendViewScrolledAccessibilityEventCallback() {
14919        if (mSendViewScrolledAccessibilityEvent == null) {
14920            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
14921        }
14922        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
14923            mSendViewScrolledAccessibilityEvent.mIsPending = true;
14924            postDelayed(mSendViewScrolledAccessibilityEvent,
14925                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
14926        }
14927    }
14928
14929    /**
14930     * Called by a parent to request that a child update its values for mScrollX
14931     * and mScrollY if necessary. This will typically be done if the child is
14932     * animating a scroll using a {@link android.widget.Scroller Scroller}
14933     * object.
14934     */
14935    public void computeScroll() {
14936    }
14937
14938    /**
14939     * <p>Indicate whether the horizontal edges are faded when the view is
14940     * scrolled horizontally.</p>
14941     *
14942     * @return true if the horizontal edges should are faded on scroll, false
14943     *         otherwise
14944     *
14945     * @see #setHorizontalFadingEdgeEnabled(boolean)
14946     *
14947     * @attr ref android.R.styleable#View_requiresFadingEdge
14948     */
14949    public boolean isHorizontalFadingEdgeEnabled() {
14950        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
14951    }
14952
14953    /**
14954     * <p>Define whether the horizontal edges should be faded when this view
14955     * is scrolled horizontally.</p>
14956     *
14957     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
14958     *                                    be faded when the view is scrolled
14959     *                                    horizontally
14960     *
14961     * @see #isHorizontalFadingEdgeEnabled()
14962     *
14963     * @attr ref android.R.styleable#View_requiresFadingEdge
14964     */
14965    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
14966        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
14967            if (horizontalFadingEdgeEnabled) {
14968                initScrollCache();
14969            }
14970
14971            mViewFlags ^= FADING_EDGE_HORIZONTAL;
14972        }
14973    }
14974
14975    /**
14976     * <p>Indicate whether the vertical edges are faded when the view is
14977     * scrolled horizontally.</p>
14978     *
14979     * @return true if the vertical edges should are faded on scroll, false
14980     *         otherwise
14981     *
14982     * @see #setVerticalFadingEdgeEnabled(boolean)
14983     *
14984     * @attr ref android.R.styleable#View_requiresFadingEdge
14985     */
14986    public boolean isVerticalFadingEdgeEnabled() {
14987        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
14988    }
14989
14990    /**
14991     * <p>Define whether the vertical edges should be faded when this view
14992     * is scrolled vertically.</p>
14993     *
14994     * @param verticalFadingEdgeEnabled true if the vertical edges should
14995     *                                  be faded when the view is scrolled
14996     *                                  vertically
14997     *
14998     * @see #isVerticalFadingEdgeEnabled()
14999     *
15000     * @attr ref android.R.styleable#View_requiresFadingEdge
15001     */
15002    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
15003        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
15004            if (verticalFadingEdgeEnabled) {
15005                initScrollCache();
15006            }
15007
15008            mViewFlags ^= FADING_EDGE_VERTICAL;
15009        }
15010    }
15011
15012    /**
15013     * Returns the strength, or intensity, of the top faded edge. The strength is
15014     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15015     * returns 0.0 or 1.0 but no value in between.
15016     *
15017     * Subclasses should override this method to provide a smoother fade transition
15018     * when scrolling occurs.
15019     *
15020     * @return the intensity of the top fade as a float between 0.0f and 1.0f
15021     */
15022    protected float getTopFadingEdgeStrength() {
15023        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
15024    }
15025
15026    /**
15027     * Returns the strength, or intensity, of the bottom faded edge. The strength is
15028     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15029     * returns 0.0 or 1.0 but no value in between.
15030     *
15031     * Subclasses should override this method to provide a smoother fade transition
15032     * when scrolling occurs.
15033     *
15034     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
15035     */
15036    protected float getBottomFadingEdgeStrength() {
15037        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
15038                computeVerticalScrollRange() ? 1.0f : 0.0f;
15039    }
15040
15041    /**
15042     * Returns the strength, or intensity, of the left faded edge. The strength is
15043     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15044     * returns 0.0 or 1.0 but no value in between.
15045     *
15046     * Subclasses should override this method to provide a smoother fade transition
15047     * when scrolling occurs.
15048     *
15049     * @return the intensity of the left fade as a float between 0.0f and 1.0f
15050     */
15051    protected float getLeftFadingEdgeStrength() {
15052        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
15053    }
15054
15055    /**
15056     * Returns the strength, or intensity, of the right faded edge. The strength is
15057     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15058     * returns 0.0 or 1.0 but no value in between.
15059     *
15060     * Subclasses should override this method to provide a smoother fade transition
15061     * when scrolling occurs.
15062     *
15063     * @return the intensity of the right fade as a float between 0.0f and 1.0f
15064     */
15065    protected float getRightFadingEdgeStrength() {
15066        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
15067                computeHorizontalScrollRange() ? 1.0f : 0.0f;
15068    }
15069
15070    /**
15071     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
15072     * scrollbar is not drawn by default.</p>
15073     *
15074     * @return true if the horizontal scrollbar should be painted, false
15075     *         otherwise
15076     *
15077     * @see #setHorizontalScrollBarEnabled(boolean)
15078     */
15079    public boolean isHorizontalScrollBarEnabled() {
15080        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
15081    }
15082
15083    /**
15084     * <p>Define whether the horizontal scrollbar should be drawn or not. The
15085     * scrollbar is not drawn by default.</p>
15086     *
15087     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
15088     *                                   be painted
15089     *
15090     * @see #isHorizontalScrollBarEnabled()
15091     */
15092    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
15093        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
15094            mViewFlags ^= SCROLLBARS_HORIZONTAL;
15095            computeOpaqueFlags();
15096            resolvePadding();
15097        }
15098    }
15099
15100    /**
15101     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
15102     * scrollbar is not drawn by default.</p>
15103     *
15104     * @return true if the vertical scrollbar should be painted, false
15105     *         otherwise
15106     *
15107     * @see #setVerticalScrollBarEnabled(boolean)
15108     */
15109    public boolean isVerticalScrollBarEnabled() {
15110        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
15111    }
15112
15113    /**
15114     * <p>Define whether the vertical scrollbar should be drawn or not. The
15115     * scrollbar is not drawn by default.</p>
15116     *
15117     * @param verticalScrollBarEnabled true if the vertical scrollbar should
15118     *                                 be painted
15119     *
15120     * @see #isVerticalScrollBarEnabled()
15121     */
15122    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
15123        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
15124            mViewFlags ^= SCROLLBARS_VERTICAL;
15125            computeOpaqueFlags();
15126            resolvePadding();
15127        }
15128    }
15129
15130    /**
15131     * @hide
15132     */
15133    protected void recomputePadding() {
15134        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15135    }
15136
15137    /**
15138     * Define whether scrollbars will fade when the view is not scrolling.
15139     *
15140     * @param fadeScrollbars whether to enable fading
15141     *
15142     * @attr ref android.R.styleable#View_fadeScrollbars
15143     */
15144    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
15145        initScrollCache();
15146        final ScrollabilityCache scrollabilityCache = mScrollCache;
15147        scrollabilityCache.fadeScrollBars = fadeScrollbars;
15148        if (fadeScrollbars) {
15149            scrollabilityCache.state = ScrollabilityCache.OFF;
15150        } else {
15151            scrollabilityCache.state = ScrollabilityCache.ON;
15152        }
15153    }
15154
15155    /**
15156     *
15157     * Returns true if scrollbars will fade when this view is not scrolling
15158     *
15159     * @return true if scrollbar fading is enabled
15160     *
15161     * @attr ref android.R.styleable#View_fadeScrollbars
15162     */
15163    public boolean isScrollbarFadingEnabled() {
15164        return mScrollCache != null && mScrollCache.fadeScrollBars;
15165    }
15166
15167    /**
15168     *
15169     * Returns the delay before scrollbars fade.
15170     *
15171     * @return the delay before scrollbars fade
15172     *
15173     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15174     */
15175    public int getScrollBarDefaultDelayBeforeFade() {
15176        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
15177                mScrollCache.scrollBarDefaultDelayBeforeFade;
15178    }
15179
15180    /**
15181     * Define the delay before scrollbars fade.
15182     *
15183     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
15184     *
15185     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15186     */
15187    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
15188        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
15189    }
15190
15191    /**
15192     *
15193     * Returns the scrollbar fade duration.
15194     *
15195     * @return the scrollbar fade duration, in milliseconds
15196     *
15197     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15198     */
15199    public int getScrollBarFadeDuration() {
15200        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
15201                mScrollCache.scrollBarFadeDuration;
15202    }
15203
15204    /**
15205     * Define the scrollbar fade duration.
15206     *
15207     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
15208     *
15209     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15210     */
15211    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
15212        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
15213    }
15214
15215    /**
15216     *
15217     * Returns the scrollbar size.
15218     *
15219     * @return the scrollbar size
15220     *
15221     * @attr ref android.R.styleable#View_scrollbarSize
15222     */
15223    public int getScrollBarSize() {
15224        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
15225                mScrollCache.scrollBarSize;
15226    }
15227
15228    /**
15229     * Define the scrollbar size.
15230     *
15231     * @param scrollBarSize - the scrollbar size
15232     *
15233     * @attr ref android.R.styleable#View_scrollbarSize
15234     */
15235    public void setScrollBarSize(int scrollBarSize) {
15236        getScrollCache().scrollBarSize = scrollBarSize;
15237    }
15238
15239    /**
15240     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
15241     * inset. When inset, they add to the padding of the view. And the scrollbars
15242     * can be drawn inside the padding area or on the edge of the view. For example,
15243     * if a view has a background drawable and you want to draw the scrollbars
15244     * inside the padding specified by the drawable, you can use
15245     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
15246     * appear at the edge of the view, ignoring the padding, then you can use
15247     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
15248     * @param style the style of the scrollbars. Should be one of
15249     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
15250     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
15251     * @see #SCROLLBARS_INSIDE_OVERLAY
15252     * @see #SCROLLBARS_INSIDE_INSET
15253     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15254     * @see #SCROLLBARS_OUTSIDE_INSET
15255     *
15256     * @attr ref android.R.styleable#View_scrollbarStyle
15257     */
15258    public void setScrollBarStyle(@ScrollBarStyle int style) {
15259        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
15260            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
15261            computeOpaqueFlags();
15262            resolvePadding();
15263        }
15264    }
15265
15266    /**
15267     * <p>Returns the current scrollbar style.</p>
15268     * @return the current scrollbar style
15269     * @see #SCROLLBARS_INSIDE_OVERLAY
15270     * @see #SCROLLBARS_INSIDE_INSET
15271     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15272     * @see #SCROLLBARS_OUTSIDE_INSET
15273     *
15274     * @attr ref android.R.styleable#View_scrollbarStyle
15275     */
15276    @ViewDebug.ExportedProperty(mapping = {
15277            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
15278            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
15279            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
15280            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
15281    })
15282    @ScrollBarStyle
15283    public int getScrollBarStyle() {
15284        return mViewFlags & SCROLLBARS_STYLE_MASK;
15285    }
15286
15287    /**
15288     * <p>Compute the horizontal range that the horizontal scrollbar
15289     * represents.</p>
15290     *
15291     * <p>The range is expressed in arbitrary units that must be the same as the
15292     * units used by {@link #computeHorizontalScrollExtent()} and
15293     * {@link #computeHorizontalScrollOffset()}.</p>
15294     *
15295     * <p>The default range is the drawing width of this view.</p>
15296     *
15297     * @return the total horizontal range represented by the horizontal
15298     *         scrollbar
15299     *
15300     * @see #computeHorizontalScrollExtent()
15301     * @see #computeHorizontalScrollOffset()
15302     * @see android.widget.ScrollBarDrawable
15303     */
15304    protected int computeHorizontalScrollRange() {
15305        return getWidth();
15306    }
15307
15308    /**
15309     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
15310     * within the horizontal range. This value is used to compute the position
15311     * of the thumb within the scrollbar's track.</p>
15312     *
15313     * <p>The range is expressed in arbitrary units that must be the same as the
15314     * units used by {@link #computeHorizontalScrollRange()} and
15315     * {@link #computeHorizontalScrollExtent()}.</p>
15316     *
15317     * <p>The default offset is the scroll offset of this view.</p>
15318     *
15319     * @return the horizontal offset of the scrollbar's thumb
15320     *
15321     * @see #computeHorizontalScrollRange()
15322     * @see #computeHorizontalScrollExtent()
15323     * @see android.widget.ScrollBarDrawable
15324     */
15325    protected int computeHorizontalScrollOffset() {
15326        return mScrollX;
15327    }
15328
15329    /**
15330     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
15331     * within the horizontal range. This value is used to compute the length
15332     * of the thumb within the scrollbar's track.</p>
15333     *
15334     * <p>The range is expressed in arbitrary units that must be the same as the
15335     * units used by {@link #computeHorizontalScrollRange()} and
15336     * {@link #computeHorizontalScrollOffset()}.</p>
15337     *
15338     * <p>The default extent is the drawing width of this view.</p>
15339     *
15340     * @return the horizontal extent of the scrollbar's thumb
15341     *
15342     * @see #computeHorizontalScrollRange()
15343     * @see #computeHorizontalScrollOffset()
15344     * @see android.widget.ScrollBarDrawable
15345     */
15346    protected int computeHorizontalScrollExtent() {
15347        return getWidth();
15348    }
15349
15350    /**
15351     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
15352     *
15353     * <p>The range is expressed in arbitrary units that must be the same as the
15354     * units used by {@link #computeVerticalScrollExtent()} and
15355     * {@link #computeVerticalScrollOffset()}.</p>
15356     *
15357     * @return the total vertical range represented by the vertical scrollbar
15358     *
15359     * <p>The default range is the drawing height of this view.</p>
15360     *
15361     * @see #computeVerticalScrollExtent()
15362     * @see #computeVerticalScrollOffset()
15363     * @see android.widget.ScrollBarDrawable
15364     */
15365    protected int computeVerticalScrollRange() {
15366        return getHeight();
15367    }
15368
15369    /**
15370     * <p>Compute the vertical offset of the vertical scrollbar's thumb
15371     * within the horizontal range. This value is used to compute the position
15372     * of the thumb within the scrollbar's track.</p>
15373     *
15374     * <p>The range is expressed in arbitrary units that must be the same as the
15375     * units used by {@link #computeVerticalScrollRange()} and
15376     * {@link #computeVerticalScrollExtent()}.</p>
15377     *
15378     * <p>The default offset is the scroll offset of this view.</p>
15379     *
15380     * @return the vertical offset of the scrollbar's thumb
15381     *
15382     * @see #computeVerticalScrollRange()
15383     * @see #computeVerticalScrollExtent()
15384     * @see android.widget.ScrollBarDrawable
15385     */
15386    protected int computeVerticalScrollOffset() {
15387        return mScrollY;
15388    }
15389
15390    /**
15391     * <p>Compute the vertical extent of the vertical scrollbar's thumb
15392     * within the vertical range. This value is used to compute the length
15393     * of the thumb within the scrollbar's track.</p>
15394     *
15395     * <p>The range is expressed in arbitrary units that must be the same as the
15396     * units used by {@link #computeVerticalScrollRange()} and
15397     * {@link #computeVerticalScrollOffset()}.</p>
15398     *
15399     * <p>The default extent is the drawing height of this view.</p>
15400     *
15401     * @return the vertical extent of the scrollbar's thumb
15402     *
15403     * @see #computeVerticalScrollRange()
15404     * @see #computeVerticalScrollOffset()
15405     * @see android.widget.ScrollBarDrawable
15406     */
15407    protected int computeVerticalScrollExtent() {
15408        return getHeight();
15409    }
15410
15411    /**
15412     * Check if this view can be scrolled horizontally in a certain direction.
15413     *
15414     * @param direction Negative to check scrolling left, positive to check scrolling right.
15415     * @return true if this view can be scrolled in the specified direction, false otherwise.
15416     */
15417    public boolean canScrollHorizontally(int direction) {
15418        final int offset = computeHorizontalScrollOffset();
15419        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
15420        if (range == 0) return false;
15421        if (direction < 0) {
15422            return offset > 0;
15423        } else {
15424            return offset < range - 1;
15425        }
15426    }
15427
15428    /**
15429     * Check if this view can be scrolled vertically in a certain direction.
15430     *
15431     * @param direction Negative to check scrolling up, positive to check scrolling down.
15432     * @return true if this view can be scrolled in the specified direction, false otherwise.
15433     */
15434    public boolean canScrollVertically(int direction) {
15435        final int offset = computeVerticalScrollOffset();
15436        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
15437        if (range == 0) return false;
15438        if (direction < 0) {
15439            return offset > 0;
15440        } else {
15441            return offset < range - 1;
15442        }
15443    }
15444
15445    void getScrollIndicatorBounds(@NonNull Rect out) {
15446        out.left = mScrollX;
15447        out.right = mScrollX + mRight - mLeft;
15448        out.top = mScrollY;
15449        out.bottom = mScrollY + mBottom - mTop;
15450    }
15451
15452    private void onDrawScrollIndicators(Canvas c) {
15453        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
15454            // No scroll indicators enabled.
15455            return;
15456        }
15457
15458        final Drawable dr = mScrollIndicatorDrawable;
15459        if (dr == null) {
15460            // Scroll indicators aren't supported here.
15461            return;
15462        }
15463
15464        final int h = dr.getIntrinsicHeight();
15465        final int w = dr.getIntrinsicWidth();
15466        final Rect rect = mAttachInfo.mTmpInvalRect;
15467        getScrollIndicatorBounds(rect);
15468
15469        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
15470            final boolean canScrollUp = canScrollVertically(-1);
15471            if (canScrollUp) {
15472                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
15473                dr.draw(c);
15474            }
15475        }
15476
15477        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
15478            final boolean canScrollDown = canScrollVertically(1);
15479            if (canScrollDown) {
15480                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
15481                dr.draw(c);
15482            }
15483        }
15484
15485        final int leftRtl;
15486        final int rightRtl;
15487        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15488            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
15489            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
15490        } else {
15491            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
15492            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
15493        }
15494
15495        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
15496        if ((mPrivateFlags3 & leftMask) != 0) {
15497            final boolean canScrollLeft = canScrollHorizontally(-1);
15498            if (canScrollLeft) {
15499                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
15500                dr.draw(c);
15501            }
15502        }
15503
15504        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
15505        if ((mPrivateFlags3 & rightMask) != 0) {
15506            final boolean canScrollRight = canScrollHorizontally(1);
15507            if (canScrollRight) {
15508                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
15509                dr.draw(c);
15510            }
15511        }
15512    }
15513
15514    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
15515            @Nullable Rect touchBounds) {
15516        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
15517        if (bounds == null) {
15518            return;
15519        }
15520        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
15521        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
15522                && !isVerticalScrollBarHidden();
15523        final int size = getHorizontalScrollbarHeight();
15524        final int verticalScrollBarGap = drawVerticalScrollBar ?
15525                getVerticalScrollbarWidth() : 0;
15526        final int width = mRight - mLeft;
15527        final int height = mBottom - mTop;
15528        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
15529        bounds.left = mScrollX + (mPaddingLeft & inside);
15530        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
15531        bounds.bottom = bounds.top + size;
15532
15533        if (touchBounds == null) {
15534            return;
15535        }
15536        if (touchBounds != bounds) {
15537            touchBounds.set(bounds);
15538        }
15539        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
15540        if (touchBounds.height() < minTouchTarget) {
15541            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
15542            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
15543            touchBounds.top = touchBounds.bottom - minTouchTarget;
15544        }
15545        if (touchBounds.width() < minTouchTarget) {
15546            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
15547            touchBounds.left -= adjust;
15548            touchBounds.right = touchBounds.left + minTouchTarget;
15549        }
15550    }
15551
15552    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
15553        if (mRoundScrollbarRenderer == null) {
15554            getStraightVerticalScrollBarBounds(bounds, touchBounds);
15555        } else {
15556            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
15557        }
15558    }
15559
15560    private void getRoundVerticalScrollBarBounds(Rect bounds) {
15561        final int width = mRight - mLeft;
15562        final int height = mBottom - mTop;
15563        // Do not take padding into account as we always want the scrollbars
15564        // to hug the screen for round wearable devices.
15565        bounds.left = mScrollX;
15566        bounds.top = mScrollY;
15567        bounds.right = bounds.left + width;
15568        bounds.bottom = mScrollY + height;
15569    }
15570
15571    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
15572            @Nullable Rect touchBounds) {
15573        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
15574        if (bounds == null) {
15575            return;
15576        }
15577        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
15578        final int size = getVerticalScrollbarWidth();
15579        int verticalScrollbarPosition = mVerticalScrollbarPosition;
15580        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
15581            verticalScrollbarPosition = isLayoutRtl() ?
15582                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
15583        }
15584        final int width = mRight - mLeft;
15585        final int height = mBottom - mTop;
15586        switch (verticalScrollbarPosition) {
15587            default:
15588            case SCROLLBAR_POSITION_RIGHT:
15589                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
15590                break;
15591            case SCROLLBAR_POSITION_LEFT:
15592                bounds.left = mScrollX + (mUserPaddingLeft & inside);
15593                break;
15594        }
15595        bounds.top = mScrollY + (mPaddingTop & inside);
15596        bounds.right = bounds.left + size;
15597        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
15598
15599        if (touchBounds == null) {
15600            return;
15601        }
15602        if (touchBounds != bounds) {
15603            touchBounds.set(bounds);
15604        }
15605        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
15606        if (touchBounds.width() < minTouchTarget) {
15607            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
15608            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
15609                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
15610                touchBounds.left = touchBounds.right - minTouchTarget;
15611            } else {
15612                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
15613                touchBounds.right = touchBounds.left + minTouchTarget;
15614            }
15615        }
15616        if (touchBounds.height() < minTouchTarget) {
15617            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
15618            touchBounds.top -= adjust;
15619            touchBounds.bottom = touchBounds.top + minTouchTarget;
15620        }
15621    }
15622
15623    /**
15624     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
15625     * scrollbars are painted only if they have been awakened first.</p>
15626     *
15627     * @param canvas the canvas on which to draw the scrollbars
15628     *
15629     * @see #awakenScrollBars(int)
15630     */
15631    protected final void onDrawScrollBars(Canvas canvas) {
15632        // scrollbars are drawn only when the animation is running
15633        final ScrollabilityCache cache = mScrollCache;
15634
15635        if (cache != null) {
15636
15637            int state = cache.state;
15638
15639            if (state == ScrollabilityCache.OFF) {
15640                return;
15641            }
15642
15643            boolean invalidate = false;
15644
15645            if (state == ScrollabilityCache.FADING) {
15646                // We're fading -- get our fade interpolation
15647                if (cache.interpolatorValues == null) {
15648                    cache.interpolatorValues = new float[1];
15649                }
15650
15651                float[] values = cache.interpolatorValues;
15652
15653                // Stops the animation if we're done
15654                if (cache.scrollBarInterpolator.timeToValues(values) ==
15655                        Interpolator.Result.FREEZE_END) {
15656                    cache.state = ScrollabilityCache.OFF;
15657                } else {
15658                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
15659                }
15660
15661                // This will make the scroll bars inval themselves after
15662                // drawing. We only want this when we're fading so that
15663                // we prevent excessive redraws
15664                invalidate = true;
15665            } else {
15666                // We're just on -- but we may have been fading before so
15667                // reset alpha
15668                cache.scrollBar.mutate().setAlpha(255);
15669            }
15670
15671            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
15672            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
15673                    && !isVerticalScrollBarHidden();
15674
15675            // Fork out the scroll bar drawing for round wearable devices.
15676            if (mRoundScrollbarRenderer != null) {
15677                if (drawVerticalScrollBar) {
15678                    final Rect bounds = cache.mScrollBarBounds;
15679                    getVerticalScrollBarBounds(bounds, null);
15680                    mRoundScrollbarRenderer.drawRoundScrollbars(
15681                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
15682                    if (invalidate) {
15683                        invalidate();
15684                    }
15685                }
15686                // Do not draw horizontal scroll bars for round wearable devices.
15687            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
15688                final ScrollBarDrawable scrollBar = cache.scrollBar;
15689
15690                if (drawHorizontalScrollBar) {
15691                    scrollBar.setParameters(computeHorizontalScrollRange(),
15692                            computeHorizontalScrollOffset(),
15693                            computeHorizontalScrollExtent(), false);
15694                    final Rect bounds = cache.mScrollBarBounds;
15695                    getHorizontalScrollBarBounds(bounds, null);
15696                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
15697                            bounds.right, bounds.bottom);
15698                    if (invalidate) {
15699                        invalidate(bounds);
15700                    }
15701                }
15702
15703                if (drawVerticalScrollBar) {
15704                    scrollBar.setParameters(computeVerticalScrollRange(),
15705                            computeVerticalScrollOffset(),
15706                            computeVerticalScrollExtent(), true);
15707                    final Rect bounds = cache.mScrollBarBounds;
15708                    getVerticalScrollBarBounds(bounds, null);
15709                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
15710                            bounds.right, bounds.bottom);
15711                    if (invalidate) {
15712                        invalidate(bounds);
15713                    }
15714                }
15715            }
15716        }
15717    }
15718
15719    /**
15720     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
15721     * FastScroller is visible.
15722     * @return whether to temporarily hide the vertical scrollbar
15723     * @hide
15724     */
15725    protected boolean isVerticalScrollBarHidden() {
15726        return false;
15727    }
15728
15729    /**
15730     * <p>Draw the horizontal scrollbar if
15731     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
15732     *
15733     * @param canvas the canvas on which to draw the scrollbar
15734     * @param scrollBar the scrollbar's drawable
15735     *
15736     * @see #isHorizontalScrollBarEnabled()
15737     * @see #computeHorizontalScrollRange()
15738     * @see #computeHorizontalScrollExtent()
15739     * @see #computeHorizontalScrollOffset()
15740     * @see android.widget.ScrollBarDrawable
15741     * @hide
15742     */
15743    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
15744            int l, int t, int r, int b) {
15745        scrollBar.setBounds(l, t, r, b);
15746        scrollBar.draw(canvas);
15747    }
15748
15749    /**
15750     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
15751     * returns true.</p>
15752     *
15753     * @param canvas the canvas on which to draw the scrollbar
15754     * @param scrollBar the scrollbar's drawable
15755     *
15756     * @see #isVerticalScrollBarEnabled()
15757     * @see #computeVerticalScrollRange()
15758     * @see #computeVerticalScrollExtent()
15759     * @see #computeVerticalScrollOffset()
15760     * @see android.widget.ScrollBarDrawable
15761     * @hide
15762     */
15763    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
15764            int l, int t, int r, int b) {
15765        scrollBar.setBounds(l, t, r, b);
15766        scrollBar.draw(canvas);
15767    }
15768
15769    /**
15770     * Implement this to do your drawing.
15771     *
15772     * @param canvas the canvas on which the background will be drawn
15773     */
15774    protected void onDraw(Canvas canvas) {
15775    }
15776
15777    /*
15778     * Caller is responsible for calling requestLayout if necessary.
15779     * (This allows addViewInLayout to not request a new layout.)
15780     */
15781    void assignParent(ViewParent parent) {
15782        if (mParent == null) {
15783            mParent = parent;
15784        } else if (parent == null) {
15785            mParent = null;
15786        } else {
15787            throw new RuntimeException("view " + this + " being added, but"
15788                    + " it already has a parent");
15789        }
15790    }
15791
15792    /**
15793     * This is called when the view is attached to a window.  At this point it
15794     * has a Surface and will start drawing.  Note that this function is
15795     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
15796     * however it may be called any time before the first onDraw -- including
15797     * before or after {@link #onMeasure(int, int)}.
15798     *
15799     * @see #onDetachedFromWindow()
15800     */
15801    @CallSuper
15802    protected void onAttachedToWindow() {
15803        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
15804            mParent.requestTransparentRegion(this);
15805        }
15806
15807        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
15808
15809        jumpDrawablesToCurrentState();
15810
15811        resetSubtreeAccessibilityStateChanged();
15812
15813        // rebuild, since Outline not maintained while View is detached
15814        rebuildOutline();
15815
15816        if (isFocused()) {
15817            InputMethodManager imm = InputMethodManager.peekInstance();
15818            if (imm != null) {
15819                imm.focusIn(this);
15820            }
15821        }
15822    }
15823
15824    /**
15825     * Resolve all RTL related properties.
15826     *
15827     * @return true if resolution of RTL properties has been done
15828     *
15829     * @hide
15830     */
15831    public boolean resolveRtlPropertiesIfNeeded() {
15832        if (!needRtlPropertiesResolution()) return false;
15833
15834        // Order is important here: LayoutDirection MUST be resolved first
15835        if (!isLayoutDirectionResolved()) {
15836            resolveLayoutDirection();
15837            resolveLayoutParams();
15838        }
15839        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
15840        if (!isTextDirectionResolved()) {
15841            resolveTextDirection();
15842        }
15843        if (!isTextAlignmentResolved()) {
15844            resolveTextAlignment();
15845        }
15846        // Should resolve Drawables before Padding because we need the layout direction of the
15847        // Drawable to correctly resolve Padding.
15848        if (!areDrawablesResolved()) {
15849            resolveDrawables();
15850        }
15851        if (!isPaddingResolved()) {
15852            resolvePadding();
15853        }
15854        onRtlPropertiesChanged(getLayoutDirection());
15855        return true;
15856    }
15857
15858    /**
15859     * Reset resolution of all RTL related properties.
15860     *
15861     * @hide
15862     */
15863    public void resetRtlProperties() {
15864        resetResolvedLayoutDirection();
15865        resetResolvedTextDirection();
15866        resetResolvedTextAlignment();
15867        resetResolvedPadding();
15868        resetResolvedDrawables();
15869    }
15870
15871    /**
15872     * @see #onScreenStateChanged(int)
15873     */
15874    void dispatchScreenStateChanged(int screenState) {
15875        onScreenStateChanged(screenState);
15876    }
15877
15878    /**
15879     * This method is called whenever the state of the screen this view is
15880     * attached to changes. A state change will usually occurs when the screen
15881     * turns on or off (whether it happens automatically or the user does it
15882     * manually.)
15883     *
15884     * @param screenState The new state of the screen. Can be either
15885     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
15886     */
15887    public void onScreenStateChanged(int screenState) {
15888    }
15889
15890    /**
15891     * @see #onMovedToDisplay(int)
15892     */
15893    void dispatchMovedToDisplay(Display display) {
15894        mAttachInfo.mDisplay = display;
15895        mAttachInfo.mDisplayState = display.getState();
15896        onMovedToDisplay(display.getDisplayId());
15897    }
15898
15899    /**
15900     * Called by the system when the hosting activity is moved from one display to another without
15901     * recreation. This means that the activity is declared to handle all changes to configuration
15902     * that happened when it was switched to another display, so it wasn't destroyed and created
15903     * again. This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
15904     * applied configuration actually changed.
15905     *
15906     * <p>Use this callback to track changes to the displays if some functionality relies on an
15907     * association with some display properties.
15908     *
15909     * @param displayId The id of the display to which the view was moved.
15910     *
15911     * @see #onConfigurationChanged(Configuration)
15912     */
15913    public void onMovedToDisplay(int displayId) {
15914    }
15915
15916    /**
15917     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
15918     */
15919    private boolean hasRtlSupport() {
15920        return mContext.getApplicationInfo().hasRtlSupport();
15921    }
15922
15923    /**
15924     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
15925     * RTL not supported)
15926     */
15927    private boolean isRtlCompatibilityMode() {
15928        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
15929        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
15930    }
15931
15932    /**
15933     * @return true if RTL properties need resolution.
15934     *
15935     */
15936    private boolean needRtlPropertiesResolution() {
15937        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
15938    }
15939
15940    /**
15941     * Called when any RTL property (layout direction or text direction or text alignment) has
15942     * been changed.
15943     *
15944     * Subclasses need to override this method to take care of cached information that depends on the
15945     * resolved layout direction, or to inform child views that inherit their layout direction.
15946     *
15947     * The default implementation does nothing.
15948     *
15949     * @param layoutDirection the direction of the layout
15950     *
15951     * @see #LAYOUT_DIRECTION_LTR
15952     * @see #LAYOUT_DIRECTION_RTL
15953     */
15954    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
15955    }
15956
15957    /**
15958     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
15959     * that the parent directionality can and will be resolved before its children.
15960     *
15961     * @return true if resolution has been done, false otherwise.
15962     *
15963     * @hide
15964     */
15965    public boolean resolveLayoutDirection() {
15966        // Clear any previous layout direction resolution
15967        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
15968
15969        if (hasRtlSupport()) {
15970            // Set resolved depending on layout direction
15971            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
15972                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
15973                case LAYOUT_DIRECTION_INHERIT:
15974                    // We cannot resolve yet. LTR is by default and let the resolution happen again
15975                    // later to get the correct resolved value
15976                    if (!canResolveLayoutDirection()) return false;
15977
15978                    // Parent has not yet resolved, LTR is still the default
15979                    try {
15980                        if (!mParent.isLayoutDirectionResolved()) return false;
15981
15982                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
15983                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15984                        }
15985                    } catch (AbstractMethodError e) {
15986                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
15987                                " does not fully implement ViewParent", e);
15988                    }
15989                    break;
15990                case LAYOUT_DIRECTION_RTL:
15991                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15992                    break;
15993                case LAYOUT_DIRECTION_LOCALE:
15994                    if((LAYOUT_DIRECTION_RTL ==
15995                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
15996                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
15997                    }
15998                    break;
15999                default:
16000                    // Nothing to do, LTR by default
16001            }
16002        }
16003
16004        // Set to resolved
16005        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16006        return true;
16007    }
16008
16009    /**
16010     * Check if layout direction resolution can be done.
16011     *
16012     * @return true if layout direction resolution can be done otherwise return false.
16013     */
16014    public boolean canResolveLayoutDirection() {
16015        switch (getRawLayoutDirection()) {
16016            case LAYOUT_DIRECTION_INHERIT:
16017                if (mParent != null) {
16018                    try {
16019                        return mParent.canResolveLayoutDirection();
16020                    } catch (AbstractMethodError e) {
16021                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16022                                " does not fully implement ViewParent", e);
16023                    }
16024                }
16025                return false;
16026
16027            default:
16028                return true;
16029        }
16030    }
16031
16032    /**
16033     * Reset the resolved layout direction. Layout direction will be resolved during a call to
16034     * {@link #onMeasure(int, int)}.
16035     *
16036     * @hide
16037     */
16038    public void resetResolvedLayoutDirection() {
16039        // Reset the current resolved bits
16040        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16041    }
16042
16043    /**
16044     * @return true if the layout direction is inherited.
16045     *
16046     * @hide
16047     */
16048    public boolean isLayoutDirectionInherited() {
16049        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
16050    }
16051
16052    /**
16053     * @return true if layout direction has been resolved.
16054     */
16055    public boolean isLayoutDirectionResolved() {
16056        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16057    }
16058
16059    /**
16060     * Return if padding has been resolved
16061     *
16062     * @hide
16063     */
16064    boolean isPaddingResolved() {
16065        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
16066    }
16067
16068    /**
16069     * Resolves padding depending on layout direction, if applicable, and
16070     * recomputes internal padding values to adjust for scroll bars.
16071     *
16072     * @hide
16073     */
16074    public void resolvePadding() {
16075        final int resolvedLayoutDirection = getLayoutDirection();
16076
16077        if (!isRtlCompatibilityMode()) {
16078            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
16079            // If start / end padding are defined, they will be resolved (hence overriding) to
16080            // left / right or right / left depending on the resolved layout direction.
16081            // If start / end padding are not defined, use the left / right ones.
16082            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
16083                Rect padding = sThreadLocal.get();
16084                if (padding == null) {
16085                    padding = new Rect();
16086                    sThreadLocal.set(padding);
16087                }
16088                mBackground.getPadding(padding);
16089                if (!mLeftPaddingDefined) {
16090                    mUserPaddingLeftInitial = padding.left;
16091                }
16092                if (!mRightPaddingDefined) {
16093                    mUserPaddingRightInitial = padding.right;
16094                }
16095            }
16096            switch (resolvedLayoutDirection) {
16097                case LAYOUT_DIRECTION_RTL:
16098                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16099                        mUserPaddingRight = mUserPaddingStart;
16100                    } else {
16101                        mUserPaddingRight = mUserPaddingRightInitial;
16102                    }
16103                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16104                        mUserPaddingLeft = mUserPaddingEnd;
16105                    } else {
16106                        mUserPaddingLeft = mUserPaddingLeftInitial;
16107                    }
16108                    break;
16109                case LAYOUT_DIRECTION_LTR:
16110                default:
16111                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16112                        mUserPaddingLeft = mUserPaddingStart;
16113                    } else {
16114                        mUserPaddingLeft = mUserPaddingLeftInitial;
16115                    }
16116                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16117                        mUserPaddingRight = mUserPaddingEnd;
16118                    } else {
16119                        mUserPaddingRight = mUserPaddingRightInitial;
16120                    }
16121            }
16122
16123            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
16124        }
16125
16126        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16127        onRtlPropertiesChanged(resolvedLayoutDirection);
16128
16129        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
16130    }
16131
16132    /**
16133     * Reset the resolved layout direction.
16134     *
16135     * @hide
16136     */
16137    public void resetResolvedPadding() {
16138        resetResolvedPaddingInternal();
16139    }
16140
16141    /**
16142     * Used when we only want to reset *this* view's padding and not trigger overrides
16143     * in ViewGroup that reset children too.
16144     */
16145    void resetResolvedPaddingInternal() {
16146        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
16147    }
16148
16149    /**
16150     * This is called when the view is detached from a window.  At this point it
16151     * no longer has a surface for drawing.
16152     *
16153     * @see #onAttachedToWindow()
16154     */
16155    @CallSuper
16156    protected void onDetachedFromWindow() {
16157    }
16158
16159    /**
16160     * This is a framework-internal mirror of onDetachedFromWindow() that's called
16161     * after onDetachedFromWindow().
16162     *
16163     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
16164     * The super method should be called at the end of the overridden method to ensure
16165     * subclasses are destroyed first
16166     *
16167     * @hide
16168     */
16169    @CallSuper
16170    protected void onDetachedFromWindowInternal() {
16171        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
16172        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16173        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
16174
16175        removeUnsetPressCallback();
16176        removeLongPressCallback();
16177        removePerformClickCallback();
16178        removeSendViewScrolledAccessibilityEventCallback();
16179        stopNestedScroll();
16180
16181        // Anything that started animating right before detach should already
16182        // be in its final state when re-attached.
16183        jumpDrawablesToCurrentState();
16184
16185        destroyDrawingCache();
16186
16187        cleanupDraw();
16188        mCurrentAnimation = null;
16189
16190        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
16191            hideTooltip();
16192        }
16193    }
16194
16195    private void cleanupDraw() {
16196        resetDisplayList();
16197        if (mAttachInfo != null) {
16198            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
16199        }
16200    }
16201
16202    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
16203    }
16204
16205    /**
16206     * @return The number of times this view has been attached to a window
16207     */
16208    protected int getWindowAttachCount() {
16209        return mWindowAttachCount;
16210    }
16211
16212    /**
16213     * Retrieve a unique token identifying the window this view is attached to.
16214     * @return Return the window's token for use in
16215     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
16216     */
16217    public IBinder getWindowToken() {
16218        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
16219    }
16220
16221    /**
16222     * Retrieve the {@link WindowId} for the window this view is
16223     * currently attached to.
16224     */
16225    public WindowId getWindowId() {
16226        if (mAttachInfo == null) {
16227            return null;
16228        }
16229        if (mAttachInfo.mWindowId == null) {
16230            try {
16231                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
16232                        mAttachInfo.mWindowToken);
16233                mAttachInfo.mWindowId = new WindowId(
16234                        mAttachInfo.mIWindowId);
16235            } catch (RemoteException e) {
16236            }
16237        }
16238        return mAttachInfo.mWindowId;
16239    }
16240
16241    /**
16242     * Retrieve a unique token identifying the top-level "real" window of
16243     * the window that this view is attached to.  That is, this is like
16244     * {@link #getWindowToken}, except if the window this view in is a panel
16245     * window (attached to another containing window), then the token of
16246     * the containing window is returned instead.
16247     *
16248     * @return Returns the associated window token, either
16249     * {@link #getWindowToken()} or the containing window's token.
16250     */
16251    public IBinder getApplicationWindowToken() {
16252        AttachInfo ai = mAttachInfo;
16253        if (ai != null) {
16254            IBinder appWindowToken = ai.mPanelParentWindowToken;
16255            if (appWindowToken == null) {
16256                appWindowToken = ai.mWindowToken;
16257            }
16258            return appWindowToken;
16259        }
16260        return null;
16261    }
16262
16263    /**
16264     * Gets the logical display to which the view's window has been attached.
16265     *
16266     * @return The logical display, or null if the view is not currently attached to a window.
16267     */
16268    public Display getDisplay() {
16269        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
16270    }
16271
16272    /**
16273     * Retrieve private session object this view hierarchy is using to
16274     * communicate with the window manager.
16275     * @return the session object to communicate with the window manager
16276     */
16277    /*package*/ IWindowSession getWindowSession() {
16278        return mAttachInfo != null ? mAttachInfo.mSession : null;
16279    }
16280
16281    /**
16282     * Return the visibility value of the least visible component passed.
16283     */
16284    int combineVisibility(int vis1, int vis2) {
16285        // This works because VISIBLE < INVISIBLE < GONE.
16286        return Math.max(vis1, vis2);
16287    }
16288
16289    /**
16290     * @param info the {@link android.view.View.AttachInfo} to associated with
16291     *        this view
16292     */
16293    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
16294        mAttachInfo = info;
16295        if (mOverlay != null) {
16296            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
16297        }
16298        mWindowAttachCount++;
16299        // We will need to evaluate the drawable state at least once.
16300        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16301        if (mFloatingTreeObserver != null) {
16302            info.mTreeObserver.merge(mFloatingTreeObserver);
16303            mFloatingTreeObserver = null;
16304        }
16305
16306        registerPendingFrameMetricsObservers();
16307
16308        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
16309            mAttachInfo.mScrollContainers.add(this);
16310            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
16311        }
16312        // Transfer all pending runnables.
16313        if (mRunQueue != null) {
16314            mRunQueue.executeActions(info.mHandler);
16315            mRunQueue = null;
16316        }
16317        performCollectViewAttributes(mAttachInfo, visibility);
16318        onAttachedToWindow();
16319
16320        ListenerInfo li = mListenerInfo;
16321        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16322                li != null ? li.mOnAttachStateChangeListeners : null;
16323        if (listeners != null && listeners.size() > 0) {
16324            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16325            // perform the dispatching. The iterator is a safe guard against listeners that
16326            // could mutate the list by calling the various add/remove methods. This prevents
16327            // the array from being modified while we iterate it.
16328            for (OnAttachStateChangeListener listener : listeners) {
16329                listener.onViewAttachedToWindow(this);
16330            }
16331        }
16332
16333        int vis = info.mWindowVisibility;
16334        if (vis != GONE) {
16335            onWindowVisibilityChanged(vis);
16336            if (isShown()) {
16337                // Calling onVisibilityAggregated directly here since the subtree will also
16338                // receive dispatchAttachedToWindow and this same call
16339                onVisibilityAggregated(vis == VISIBLE);
16340            }
16341        }
16342
16343        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
16344        // As all views in the subtree will already receive dispatchAttachedToWindow
16345        // traversing the subtree again here is not desired.
16346        onVisibilityChanged(this, visibility);
16347
16348        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
16349            // If nobody has evaluated the drawable state yet, then do it now.
16350            refreshDrawableState();
16351        }
16352        needGlobalAttributesUpdate(false);
16353    }
16354
16355    void dispatchDetachedFromWindow() {
16356        AttachInfo info = mAttachInfo;
16357        if (info != null) {
16358            int vis = info.mWindowVisibility;
16359            if (vis != GONE) {
16360                onWindowVisibilityChanged(GONE);
16361                if (isShown()) {
16362                    // Invoking onVisibilityAggregated directly here since the subtree
16363                    // will also receive detached from window
16364                    onVisibilityAggregated(false);
16365                }
16366            }
16367        }
16368
16369        onDetachedFromWindow();
16370        onDetachedFromWindowInternal();
16371
16372        InputMethodManager imm = InputMethodManager.peekInstance();
16373        if (imm != null) {
16374            imm.onViewDetachedFromWindow(this);
16375        }
16376
16377        ListenerInfo li = mListenerInfo;
16378        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16379                li != null ? li.mOnAttachStateChangeListeners : null;
16380        if (listeners != null && listeners.size() > 0) {
16381            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16382            // perform the dispatching. The iterator is a safe guard against listeners that
16383            // could mutate the list by calling the various add/remove methods. This prevents
16384            // the array from being modified while we iterate it.
16385            for (OnAttachStateChangeListener listener : listeners) {
16386                listener.onViewDetachedFromWindow(this);
16387            }
16388        }
16389
16390        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
16391            mAttachInfo.mScrollContainers.remove(this);
16392            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
16393        }
16394
16395        mAttachInfo = null;
16396        if (mOverlay != null) {
16397            mOverlay.getOverlayView().dispatchDetachedFromWindow();
16398        }
16399    }
16400
16401    /**
16402     * Cancel any deferred high-level input events that were previously posted to the event queue.
16403     *
16404     * <p>Many views post high-level events such as click handlers to the event queue
16405     * to run deferred in order to preserve a desired user experience - clearing visible
16406     * pressed states before executing, etc. This method will abort any events of this nature
16407     * that are currently in flight.</p>
16408     *
16409     * <p>Custom views that generate their own high-level deferred input events should override
16410     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
16411     *
16412     * <p>This will also cancel pending input events for any child views.</p>
16413     *
16414     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
16415     * This will not impact newer events posted after this call that may occur as a result of
16416     * lower-level input events still waiting in the queue. If you are trying to prevent
16417     * double-submitted  events for the duration of some sort of asynchronous transaction
16418     * you should also take other steps to protect against unexpected double inputs e.g. calling
16419     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
16420     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
16421     */
16422    public final void cancelPendingInputEvents() {
16423        dispatchCancelPendingInputEvents();
16424    }
16425
16426    /**
16427     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
16428     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
16429     */
16430    void dispatchCancelPendingInputEvents() {
16431        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
16432        onCancelPendingInputEvents();
16433        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
16434            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
16435                    " did not call through to super.onCancelPendingInputEvents()");
16436        }
16437    }
16438
16439    /**
16440     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
16441     * a parent view.
16442     *
16443     * <p>This method is responsible for removing any pending high-level input events that were
16444     * posted to the event queue to run later. Custom view classes that post their own deferred
16445     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
16446     * {@link android.os.Handler} should override this method, call
16447     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
16448     * </p>
16449     */
16450    public void onCancelPendingInputEvents() {
16451        removePerformClickCallback();
16452        cancelLongPress();
16453        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
16454    }
16455
16456    /**
16457     * Store this view hierarchy's frozen state into the given container.
16458     *
16459     * @param container The SparseArray in which to save the view's state.
16460     *
16461     * @see #restoreHierarchyState(android.util.SparseArray)
16462     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16463     * @see #onSaveInstanceState()
16464     */
16465    public void saveHierarchyState(SparseArray<Parcelable> container) {
16466        dispatchSaveInstanceState(container);
16467    }
16468
16469    /**
16470     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
16471     * this view and its children. May be overridden to modify how freezing happens to a
16472     * view's children; for example, some views may want to not store state for their children.
16473     *
16474     * @param container The SparseArray in which to save the view's state.
16475     *
16476     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16477     * @see #saveHierarchyState(android.util.SparseArray)
16478     * @see #onSaveInstanceState()
16479     */
16480    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
16481        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
16482            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
16483            Parcelable state = onSaveInstanceState();
16484            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
16485                throw new IllegalStateException(
16486                        "Derived class did not call super.onSaveInstanceState()");
16487            }
16488            if (state != null) {
16489                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
16490                // + ": " + state);
16491                container.put(mID, state);
16492            }
16493        }
16494    }
16495
16496    /**
16497     * Hook allowing a view to generate a representation of its internal state
16498     * that can later be used to create a new instance with that same state.
16499     * This state should only contain information that is not persistent or can
16500     * not be reconstructed later. For example, you will never store your
16501     * current position on screen because that will be computed again when a
16502     * new instance of the view is placed in its view hierarchy.
16503     * <p>
16504     * Some examples of things you may store here: the current cursor position
16505     * in a text view (but usually not the text itself since that is stored in a
16506     * content provider or other persistent storage), the currently selected
16507     * item in a list view.
16508     *
16509     * @return Returns a Parcelable object containing the view's current dynamic
16510     *         state, or null if there is nothing interesting to save. The
16511     *         default implementation returns null.
16512     * @see #onRestoreInstanceState(android.os.Parcelable)
16513     * @see #saveHierarchyState(android.util.SparseArray)
16514     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16515     * @see #setSaveEnabled(boolean)
16516     */
16517    @CallSuper
16518    protected Parcelable onSaveInstanceState() {
16519        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
16520        if (mStartActivityRequestWho != null) {
16521            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
16522            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
16523            return state;
16524        }
16525        return BaseSavedState.EMPTY_STATE;
16526    }
16527
16528    /**
16529     * Restore this view hierarchy's frozen state from the given container.
16530     *
16531     * @param container The SparseArray which holds previously frozen states.
16532     *
16533     * @see #saveHierarchyState(android.util.SparseArray)
16534     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16535     * @see #onRestoreInstanceState(android.os.Parcelable)
16536     */
16537    public void restoreHierarchyState(SparseArray<Parcelable> container) {
16538        dispatchRestoreInstanceState(container);
16539    }
16540
16541    /**
16542     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
16543     * state for this view and its children. May be overridden to modify how restoring
16544     * happens to a view's children; for example, some views may want to not store state
16545     * for their children.
16546     *
16547     * @param container The SparseArray which holds previously saved state.
16548     *
16549     * @see #dispatchSaveInstanceState(android.util.SparseArray)
16550     * @see #restoreHierarchyState(android.util.SparseArray)
16551     * @see #onRestoreInstanceState(android.os.Parcelable)
16552     */
16553    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
16554        if (mID != NO_ID) {
16555            Parcelable state = container.get(mID);
16556            if (state != null) {
16557                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
16558                // + ": " + state);
16559                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
16560                onRestoreInstanceState(state);
16561                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
16562                    throw new IllegalStateException(
16563                            "Derived class did not call super.onRestoreInstanceState()");
16564                }
16565            }
16566        }
16567    }
16568
16569    /**
16570     * Hook allowing a view to re-apply a representation of its internal state that had previously
16571     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
16572     * null state.
16573     *
16574     * @param state The frozen state that had previously been returned by
16575     *        {@link #onSaveInstanceState}.
16576     *
16577     * @see #onSaveInstanceState()
16578     * @see #restoreHierarchyState(android.util.SparseArray)
16579     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
16580     */
16581    @CallSuper
16582    protected void onRestoreInstanceState(Parcelable state) {
16583        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
16584        if (state != null && !(state instanceof AbsSavedState)) {
16585            throw new IllegalArgumentException("Wrong state class, expecting View State but "
16586                    + "received " + state.getClass().toString() + " instead. This usually happens "
16587                    + "when two views of different type have the same id in the same hierarchy. "
16588                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
16589                    + "other views do not use the same id.");
16590        }
16591        if (state != null && state instanceof BaseSavedState) {
16592            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
16593        }
16594    }
16595
16596    /**
16597     * <p>Return the time at which the drawing of the view hierarchy started.</p>
16598     *
16599     * @return the drawing start time in milliseconds
16600     */
16601    public long getDrawingTime() {
16602        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
16603    }
16604
16605    /**
16606     * <p>Enables or disables the duplication of the parent's state into this view. When
16607     * duplication is enabled, this view gets its drawable state from its parent rather
16608     * than from its own internal properties.</p>
16609     *
16610     * <p>Note: in the current implementation, setting this property to true after the
16611     * view was added to a ViewGroup might have no effect at all. This property should
16612     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
16613     *
16614     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
16615     * property is enabled, an exception will be thrown.</p>
16616     *
16617     * <p>Note: if the child view uses and updates additional states which are unknown to the
16618     * parent, these states should not be affected by this method.</p>
16619     *
16620     * @param enabled True to enable duplication of the parent's drawable state, false
16621     *                to disable it.
16622     *
16623     * @see #getDrawableState()
16624     * @see #isDuplicateParentStateEnabled()
16625     */
16626    public void setDuplicateParentStateEnabled(boolean enabled) {
16627        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
16628    }
16629
16630    /**
16631     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
16632     *
16633     * @return True if this view's drawable state is duplicated from the parent,
16634     *         false otherwise
16635     *
16636     * @see #getDrawableState()
16637     * @see #setDuplicateParentStateEnabled(boolean)
16638     */
16639    public boolean isDuplicateParentStateEnabled() {
16640        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
16641    }
16642
16643    /**
16644     * <p>Specifies the type of layer backing this view. The layer can be
16645     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16646     * {@link #LAYER_TYPE_HARDWARE}.</p>
16647     *
16648     * <p>A layer is associated with an optional {@link android.graphics.Paint}
16649     * instance that controls how the layer is composed on screen. The following
16650     * properties of the paint are taken into account when composing the layer:</p>
16651     * <ul>
16652     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
16653     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
16654     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
16655     * </ul>
16656     *
16657     * <p>If this view has an alpha value set to < 1.0 by calling
16658     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
16659     * by this view's alpha value.</p>
16660     *
16661     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
16662     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
16663     * for more information on when and how to use layers.</p>
16664     *
16665     * @param layerType The type of layer to use with this view, must be one of
16666     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16667     *        {@link #LAYER_TYPE_HARDWARE}
16668     * @param paint The paint used to compose the layer. This argument is optional
16669     *        and can be null. It is ignored when the layer type is
16670     *        {@link #LAYER_TYPE_NONE}
16671     *
16672     * @see #getLayerType()
16673     * @see #LAYER_TYPE_NONE
16674     * @see #LAYER_TYPE_SOFTWARE
16675     * @see #LAYER_TYPE_HARDWARE
16676     * @see #setAlpha(float)
16677     *
16678     * @attr ref android.R.styleable#View_layerType
16679     */
16680    public void setLayerType(int layerType, @Nullable Paint paint) {
16681        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
16682            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
16683                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
16684        }
16685
16686        boolean typeChanged = mRenderNode.setLayerType(layerType);
16687
16688        if (!typeChanged) {
16689            setLayerPaint(paint);
16690            return;
16691        }
16692
16693        if (layerType != LAYER_TYPE_SOFTWARE) {
16694            // Destroy any previous software drawing cache if present
16695            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
16696            // drawing cache created in View#draw when drawing to a SW canvas.
16697            destroyDrawingCache();
16698        }
16699
16700        mLayerType = layerType;
16701        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
16702        mRenderNode.setLayerPaint(mLayerPaint);
16703
16704        // draw() behaves differently if we are on a layer, so we need to
16705        // invalidate() here
16706        invalidateParentCaches();
16707        invalidate(true);
16708    }
16709
16710    /**
16711     * Updates the {@link Paint} object used with the current layer (used only if the current
16712     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
16713     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
16714     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
16715     * ensure that the view gets redrawn immediately.
16716     *
16717     * <p>A layer is associated with an optional {@link android.graphics.Paint}
16718     * instance that controls how the layer is composed on screen. The following
16719     * properties of the paint are taken into account when composing the layer:</p>
16720     * <ul>
16721     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
16722     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
16723     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
16724     * </ul>
16725     *
16726     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
16727     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
16728     *
16729     * @param paint The paint used to compose the layer. This argument is optional
16730     *        and can be null. It is ignored when the layer type is
16731     *        {@link #LAYER_TYPE_NONE}
16732     *
16733     * @see #setLayerType(int, android.graphics.Paint)
16734     */
16735    public void setLayerPaint(@Nullable Paint paint) {
16736        int layerType = getLayerType();
16737        if (layerType != LAYER_TYPE_NONE) {
16738            mLayerPaint = paint;
16739            if (layerType == LAYER_TYPE_HARDWARE) {
16740                if (mRenderNode.setLayerPaint(paint)) {
16741                    invalidateViewProperty(false, false);
16742                }
16743            } else {
16744                invalidate();
16745            }
16746        }
16747    }
16748
16749    /**
16750     * Indicates what type of layer is currently associated with this view. By default
16751     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
16752     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
16753     * for more information on the different types of layers.
16754     *
16755     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
16756     *         {@link #LAYER_TYPE_HARDWARE}
16757     *
16758     * @see #setLayerType(int, android.graphics.Paint)
16759     * @see #buildLayer()
16760     * @see #LAYER_TYPE_NONE
16761     * @see #LAYER_TYPE_SOFTWARE
16762     * @see #LAYER_TYPE_HARDWARE
16763     */
16764    public int getLayerType() {
16765        return mLayerType;
16766    }
16767
16768    /**
16769     * Forces this view's layer to be created and this view to be rendered
16770     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
16771     * invoking this method will have no effect.
16772     *
16773     * This method can for instance be used to render a view into its layer before
16774     * starting an animation. If this view is complex, rendering into the layer
16775     * before starting the animation will avoid skipping frames.
16776     *
16777     * @throws IllegalStateException If this view is not attached to a window
16778     *
16779     * @see #setLayerType(int, android.graphics.Paint)
16780     */
16781    public void buildLayer() {
16782        if (mLayerType == LAYER_TYPE_NONE) return;
16783
16784        final AttachInfo attachInfo = mAttachInfo;
16785        if (attachInfo == null) {
16786            throw new IllegalStateException("This view must be attached to a window first");
16787        }
16788
16789        if (getWidth() == 0 || getHeight() == 0) {
16790            return;
16791        }
16792
16793        switch (mLayerType) {
16794            case LAYER_TYPE_HARDWARE:
16795                updateDisplayListIfDirty();
16796                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
16797                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
16798                }
16799                break;
16800            case LAYER_TYPE_SOFTWARE:
16801                buildDrawingCache(true);
16802                break;
16803        }
16804    }
16805
16806    /**
16807     * Destroys all hardware rendering resources. This method is invoked
16808     * when the system needs to reclaim resources. Upon execution of this
16809     * method, you should free any OpenGL resources created by the view.
16810     *
16811     * Note: you <strong>must</strong> call
16812     * <code>super.destroyHardwareResources()</code> when overriding
16813     * this method.
16814     *
16815     * @hide
16816     */
16817    @CallSuper
16818    protected void destroyHardwareResources() {
16819        if (mOverlay != null) {
16820            mOverlay.getOverlayView().destroyHardwareResources();
16821        }
16822        if (mGhostView != null) {
16823            mGhostView.destroyHardwareResources();
16824        }
16825    }
16826
16827    /**
16828     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
16829     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
16830     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
16831     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
16832     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
16833     * null.</p>
16834     *
16835     * <p>Enabling the drawing cache is similar to
16836     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
16837     * acceleration is turned off. When hardware acceleration is turned on, enabling the
16838     * drawing cache has no effect on rendering because the system uses a different mechanism
16839     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
16840     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
16841     * for information on how to enable software and hardware layers.</p>
16842     *
16843     * <p>This API can be used to manually generate
16844     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
16845     * {@link #getDrawingCache()}.</p>
16846     *
16847     * @param enabled true to enable the drawing cache, false otherwise
16848     *
16849     * @see #isDrawingCacheEnabled()
16850     * @see #getDrawingCache()
16851     * @see #buildDrawingCache()
16852     * @see #setLayerType(int, android.graphics.Paint)
16853     */
16854    public void setDrawingCacheEnabled(boolean enabled) {
16855        mCachingFailed = false;
16856        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
16857    }
16858
16859    /**
16860     * <p>Indicates whether the drawing cache is enabled for this view.</p>
16861     *
16862     * @return true if the drawing cache is enabled
16863     *
16864     * @see #setDrawingCacheEnabled(boolean)
16865     * @see #getDrawingCache()
16866     */
16867    @ViewDebug.ExportedProperty(category = "drawing")
16868    public boolean isDrawingCacheEnabled() {
16869        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
16870    }
16871
16872    /**
16873     * Debugging utility which recursively outputs the dirty state of a view and its
16874     * descendants.
16875     *
16876     * @hide
16877     */
16878    @SuppressWarnings({"UnusedDeclaration"})
16879    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
16880        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
16881                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
16882                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
16883                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
16884        if (clear) {
16885            mPrivateFlags &= clearMask;
16886        }
16887        if (this instanceof ViewGroup) {
16888            ViewGroup parent = (ViewGroup) this;
16889            final int count = parent.getChildCount();
16890            for (int i = 0; i < count; i++) {
16891                final View child = parent.getChildAt(i);
16892                child.outputDirtyFlags(indent + "  ", clear, clearMask);
16893            }
16894        }
16895    }
16896
16897    /**
16898     * This method is used by ViewGroup to cause its children to restore or recreate their
16899     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
16900     * to recreate its own display list, which would happen if it went through the normal
16901     * draw/dispatchDraw mechanisms.
16902     *
16903     * @hide
16904     */
16905    protected void dispatchGetDisplayList() {}
16906
16907    /**
16908     * A view that is not attached or hardware accelerated cannot create a display list.
16909     * This method checks these conditions and returns the appropriate result.
16910     *
16911     * @return true if view has the ability to create a display list, false otherwise.
16912     *
16913     * @hide
16914     */
16915    public boolean canHaveDisplayList() {
16916        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
16917    }
16918
16919    /**
16920     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
16921     * @hide
16922     */
16923    @NonNull
16924    public RenderNode updateDisplayListIfDirty() {
16925        final RenderNode renderNode = mRenderNode;
16926        if (!canHaveDisplayList()) {
16927            // can't populate RenderNode, don't try
16928            return renderNode;
16929        }
16930
16931        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
16932                || !renderNode.isValid()
16933                || (mRecreateDisplayList)) {
16934            // Don't need to recreate the display list, just need to tell our
16935            // children to restore/recreate theirs
16936            if (renderNode.isValid()
16937                    && !mRecreateDisplayList) {
16938                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16939                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16940                dispatchGetDisplayList();
16941
16942                return renderNode; // no work needed
16943            }
16944
16945            // If we got here, we're recreating it. Mark it as such to ensure that
16946            // we copy in child display lists into ours in drawChild()
16947            mRecreateDisplayList = true;
16948
16949            int width = mRight - mLeft;
16950            int height = mBottom - mTop;
16951            int layerType = getLayerType();
16952
16953            final DisplayListCanvas canvas = renderNode.start(width, height);
16954            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
16955
16956            try {
16957                if (layerType == LAYER_TYPE_SOFTWARE) {
16958                    buildDrawingCache(true);
16959                    Bitmap cache = getDrawingCache(true);
16960                    if (cache != null) {
16961                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
16962                    }
16963                } else {
16964                    computeScroll();
16965
16966                    canvas.translate(-mScrollX, -mScrollY);
16967                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16968                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16969
16970                    // Fast path for layouts with no backgrounds
16971                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16972                        dispatchDraw(canvas);
16973                        if (mOverlay != null && !mOverlay.isEmpty()) {
16974                            mOverlay.getOverlayView().draw(canvas);
16975                        }
16976                        if (debugDraw()) {
16977                            debugDrawFocus(canvas);
16978                        }
16979                    } else {
16980                        draw(canvas);
16981                    }
16982                }
16983            } finally {
16984                renderNode.end(canvas);
16985                setDisplayListProperties(renderNode);
16986            }
16987        } else {
16988            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
16989            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16990        }
16991        return renderNode;
16992    }
16993
16994    private void resetDisplayList() {
16995        mRenderNode.discardDisplayList();
16996        if (mBackgroundRenderNode != null) {
16997            mBackgroundRenderNode.discardDisplayList();
16998        }
16999    }
17000
17001    /**
17002     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
17003     *
17004     * @return A non-scaled bitmap representing this view or null if cache is disabled.
17005     *
17006     * @see #getDrawingCache(boolean)
17007     */
17008    public Bitmap getDrawingCache() {
17009        return getDrawingCache(false);
17010    }
17011
17012    /**
17013     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
17014     * is null when caching is disabled. If caching is enabled and the cache is not ready,
17015     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
17016     * draw from the cache when the cache is enabled. To benefit from the cache, you must
17017     * request the drawing cache by calling this method and draw it on screen if the
17018     * returned bitmap is not null.</p>
17019     *
17020     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17021     * this method will create a bitmap of the same size as this view. Because this bitmap
17022     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17023     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17024     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17025     * size than the view. This implies that your application must be able to handle this
17026     * size.</p>
17027     *
17028     * @param autoScale Indicates whether the generated bitmap should be scaled based on
17029     *        the current density of the screen when the application is in compatibility
17030     *        mode.
17031     *
17032     * @return A bitmap representing this view or null if cache is disabled.
17033     *
17034     * @see #setDrawingCacheEnabled(boolean)
17035     * @see #isDrawingCacheEnabled()
17036     * @see #buildDrawingCache(boolean)
17037     * @see #destroyDrawingCache()
17038     */
17039    public Bitmap getDrawingCache(boolean autoScale) {
17040        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
17041            return null;
17042        }
17043        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
17044            buildDrawingCache(autoScale);
17045        }
17046        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
17047    }
17048
17049    /**
17050     * <p>Frees the resources used by the drawing cache. If you call
17051     * {@link #buildDrawingCache()} manually without calling
17052     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17053     * should cleanup the cache with this method afterwards.</p>
17054     *
17055     * @see #setDrawingCacheEnabled(boolean)
17056     * @see #buildDrawingCache()
17057     * @see #getDrawingCache()
17058     */
17059    public void destroyDrawingCache() {
17060        if (mDrawingCache != null) {
17061            mDrawingCache.recycle();
17062            mDrawingCache = null;
17063        }
17064        if (mUnscaledDrawingCache != null) {
17065            mUnscaledDrawingCache.recycle();
17066            mUnscaledDrawingCache = null;
17067        }
17068    }
17069
17070    /**
17071     * Setting a solid background color for the drawing cache's bitmaps will improve
17072     * performance and memory usage. Note, though that this should only be used if this
17073     * view will always be drawn on top of a solid color.
17074     *
17075     * @param color The background color to use for the drawing cache's bitmap
17076     *
17077     * @see #setDrawingCacheEnabled(boolean)
17078     * @see #buildDrawingCache()
17079     * @see #getDrawingCache()
17080     */
17081    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
17082        if (color != mDrawingCacheBackgroundColor) {
17083            mDrawingCacheBackgroundColor = color;
17084            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17085        }
17086    }
17087
17088    /**
17089     * @see #setDrawingCacheBackgroundColor(int)
17090     *
17091     * @return The background color to used for the drawing cache's bitmap
17092     */
17093    @ColorInt
17094    public int getDrawingCacheBackgroundColor() {
17095        return mDrawingCacheBackgroundColor;
17096    }
17097
17098    /**
17099     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
17100     *
17101     * @see #buildDrawingCache(boolean)
17102     */
17103    public void buildDrawingCache() {
17104        buildDrawingCache(false);
17105    }
17106
17107    /**
17108     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
17109     *
17110     * <p>If you call {@link #buildDrawingCache()} manually without calling
17111     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17112     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
17113     *
17114     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17115     * this method will create a bitmap of the same size as this view. Because this bitmap
17116     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17117     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17118     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17119     * size than the view. This implies that your application must be able to handle this
17120     * size.</p>
17121     *
17122     * <p>You should avoid calling this method when hardware acceleration is enabled. If
17123     * you do not need the drawing cache bitmap, calling this method will increase memory
17124     * usage and cause the view to be rendered in software once, thus negatively impacting
17125     * performance.</p>
17126     *
17127     * @see #getDrawingCache()
17128     * @see #destroyDrawingCache()
17129     */
17130    public void buildDrawingCache(boolean autoScale) {
17131        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
17132                mDrawingCache == null : mUnscaledDrawingCache == null)) {
17133            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
17134                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
17135                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
17136            }
17137            try {
17138                buildDrawingCacheImpl(autoScale);
17139            } finally {
17140                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
17141            }
17142        }
17143    }
17144
17145    /**
17146     * private, internal implementation of buildDrawingCache, used to enable tracing
17147     */
17148    private void buildDrawingCacheImpl(boolean autoScale) {
17149        mCachingFailed = false;
17150
17151        int width = mRight - mLeft;
17152        int height = mBottom - mTop;
17153
17154        final AttachInfo attachInfo = mAttachInfo;
17155        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
17156
17157        if (autoScale && scalingRequired) {
17158            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
17159            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
17160        }
17161
17162        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
17163        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
17164        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
17165
17166        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
17167        final long drawingCacheSize =
17168                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
17169        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
17170            if (width > 0 && height > 0) {
17171                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
17172                        + " too large to fit into a software layer (or drawing cache), needs "
17173                        + projectedBitmapSize + " bytes, only "
17174                        + drawingCacheSize + " available");
17175            }
17176            destroyDrawingCache();
17177            mCachingFailed = true;
17178            return;
17179        }
17180
17181        boolean clear = true;
17182        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
17183
17184        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
17185            Bitmap.Config quality;
17186            if (!opaque) {
17187                // Never pick ARGB_4444 because it looks awful
17188                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
17189                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
17190                    case DRAWING_CACHE_QUALITY_AUTO:
17191                    case DRAWING_CACHE_QUALITY_LOW:
17192                    case DRAWING_CACHE_QUALITY_HIGH:
17193                    default:
17194                        quality = Bitmap.Config.ARGB_8888;
17195                        break;
17196                }
17197            } else {
17198                // Optimization for translucent windows
17199                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
17200                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
17201            }
17202
17203            // Try to cleanup memory
17204            if (bitmap != null) bitmap.recycle();
17205
17206            try {
17207                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17208                        width, height, quality);
17209                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
17210                if (autoScale) {
17211                    mDrawingCache = bitmap;
17212                } else {
17213                    mUnscaledDrawingCache = bitmap;
17214                }
17215                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
17216            } catch (OutOfMemoryError e) {
17217                // If there is not enough memory to create the bitmap cache, just
17218                // ignore the issue as bitmap caches are not required to draw the
17219                // view hierarchy
17220                if (autoScale) {
17221                    mDrawingCache = null;
17222                } else {
17223                    mUnscaledDrawingCache = null;
17224                }
17225                mCachingFailed = true;
17226                return;
17227            }
17228
17229            clear = drawingCacheBackgroundColor != 0;
17230        }
17231
17232        Canvas canvas;
17233        if (attachInfo != null) {
17234            canvas = attachInfo.mCanvas;
17235            if (canvas == null) {
17236                canvas = new Canvas();
17237            }
17238            canvas.setBitmap(bitmap);
17239            // Temporarily clobber the cached Canvas in case one of our children
17240            // is also using a drawing cache. Without this, the children would
17241            // steal the canvas by attaching their own bitmap to it and bad, bad
17242            // thing would happen (invisible views, corrupted drawings, etc.)
17243            attachInfo.mCanvas = null;
17244        } else {
17245            // This case should hopefully never or seldom happen
17246            canvas = new Canvas(bitmap);
17247        }
17248
17249        if (clear) {
17250            bitmap.eraseColor(drawingCacheBackgroundColor);
17251        }
17252
17253        computeScroll();
17254        final int restoreCount = canvas.save();
17255
17256        if (autoScale && scalingRequired) {
17257            final float scale = attachInfo.mApplicationScale;
17258            canvas.scale(scale, scale);
17259        }
17260
17261        canvas.translate(-mScrollX, -mScrollY);
17262
17263        mPrivateFlags |= PFLAG_DRAWN;
17264        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
17265                mLayerType != LAYER_TYPE_NONE) {
17266            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
17267        }
17268
17269        // Fast path for layouts with no backgrounds
17270        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17271            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17272            dispatchDraw(canvas);
17273            if (mOverlay != null && !mOverlay.isEmpty()) {
17274                mOverlay.getOverlayView().draw(canvas);
17275            }
17276        } else {
17277            draw(canvas);
17278        }
17279
17280        canvas.restoreToCount(restoreCount);
17281        canvas.setBitmap(null);
17282
17283        if (attachInfo != null) {
17284            // Restore the cached Canvas for our siblings
17285            attachInfo.mCanvas = canvas;
17286        }
17287    }
17288
17289    /**
17290     * Create a snapshot of the view into a bitmap.  We should probably make
17291     * some form of this public, but should think about the API.
17292     *
17293     * @hide
17294     */
17295    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
17296        int width = mRight - mLeft;
17297        int height = mBottom - mTop;
17298
17299        final AttachInfo attachInfo = mAttachInfo;
17300        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
17301        width = (int) ((width * scale) + 0.5f);
17302        height = (int) ((height * scale) + 0.5f);
17303
17304        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17305                width > 0 ? width : 1, height > 0 ? height : 1, quality);
17306        if (bitmap == null) {
17307            throw new OutOfMemoryError();
17308        }
17309
17310        Resources resources = getResources();
17311        if (resources != null) {
17312            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
17313        }
17314
17315        Canvas canvas;
17316        if (attachInfo != null) {
17317            canvas = attachInfo.mCanvas;
17318            if (canvas == null) {
17319                canvas = new Canvas();
17320            }
17321            canvas.setBitmap(bitmap);
17322            // Temporarily clobber the cached Canvas in case one of our children
17323            // is also using a drawing cache. Without this, the children would
17324            // steal the canvas by attaching their own bitmap to it and bad, bad
17325            // things would happen (invisible views, corrupted drawings, etc.)
17326            attachInfo.mCanvas = null;
17327        } else {
17328            // This case should hopefully never or seldom happen
17329            canvas = new Canvas(bitmap);
17330        }
17331
17332        if ((backgroundColor & 0xff000000) != 0) {
17333            bitmap.eraseColor(backgroundColor);
17334        }
17335
17336        computeScroll();
17337        final int restoreCount = canvas.save();
17338        canvas.scale(scale, scale);
17339        canvas.translate(-mScrollX, -mScrollY);
17340
17341        // Temporarily remove the dirty mask
17342        int flags = mPrivateFlags;
17343        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17344
17345        // Fast path for layouts with no backgrounds
17346        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17347            dispatchDraw(canvas);
17348            if (mOverlay != null && !mOverlay.isEmpty()) {
17349                mOverlay.getOverlayView().draw(canvas);
17350            }
17351        } else {
17352            draw(canvas);
17353        }
17354
17355        mPrivateFlags = flags;
17356
17357        canvas.restoreToCount(restoreCount);
17358        canvas.setBitmap(null);
17359
17360        if (attachInfo != null) {
17361            // Restore the cached Canvas for our siblings
17362            attachInfo.mCanvas = canvas;
17363        }
17364
17365        return bitmap;
17366    }
17367
17368    /**
17369     * Indicates whether this View is currently in edit mode. A View is usually
17370     * in edit mode when displayed within a developer tool. For instance, if
17371     * this View is being drawn by a visual user interface builder, this method
17372     * should return true.
17373     *
17374     * Subclasses should check the return value of this method to provide
17375     * different behaviors if their normal behavior might interfere with the
17376     * host environment. For instance: the class spawns a thread in its
17377     * constructor, the drawing code relies on device-specific features, etc.
17378     *
17379     * This method is usually checked in the drawing code of custom widgets.
17380     *
17381     * @return True if this View is in edit mode, false otherwise.
17382     */
17383    public boolean isInEditMode() {
17384        return false;
17385    }
17386
17387    /**
17388     * If the View draws content inside its padding and enables fading edges,
17389     * it needs to support padding offsets. Padding offsets are added to the
17390     * fading edges to extend the length of the fade so that it covers pixels
17391     * drawn inside the padding.
17392     *
17393     * Subclasses of this class should override this method if they need
17394     * to draw content inside the padding.
17395     *
17396     * @return True if padding offset must be applied, false otherwise.
17397     *
17398     * @see #getLeftPaddingOffset()
17399     * @see #getRightPaddingOffset()
17400     * @see #getTopPaddingOffset()
17401     * @see #getBottomPaddingOffset()
17402     *
17403     * @since CURRENT
17404     */
17405    protected boolean isPaddingOffsetRequired() {
17406        return false;
17407    }
17408
17409    /**
17410     * Amount by which to extend the left fading region. Called only when
17411     * {@link #isPaddingOffsetRequired()} returns true.
17412     *
17413     * @return The left padding offset in pixels.
17414     *
17415     * @see #isPaddingOffsetRequired()
17416     *
17417     * @since CURRENT
17418     */
17419    protected int getLeftPaddingOffset() {
17420        return 0;
17421    }
17422
17423    /**
17424     * Amount by which to extend the right fading region. Called only when
17425     * {@link #isPaddingOffsetRequired()} returns true.
17426     *
17427     * @return The right padding offset in pixels.
17428     *
17429     * @see #isPaddingOffsetRequired()
17430     *
17431     * @since CURRENT
17432     */
17433    protected int getRightPaddingOffset() {
17434        return 0;
17435    }
17436
17437    /**
17438     * Amount by which to extend the top fading region. Called only when
17439     * {@link #isPaddingOffsetRequired()} returns true.
17440     *
17441     * @return The top padding offset in pixels.
17442     *
17443     * @see #isPaddingOffsetRequired()
17444     *
17445     * @since CURRENT
17446     */
17447    protected int getTopPaddingOffset() {
17448        return 0;
17449    }
17450
17451    /**
17452     * Amount by which to extend the bottom fading region. Called only when
17453     * {@link #isPaddingOffsetRequired()} returns true.
17454     *
17455     * @return The bottom padding offset in pixels.
17456     *
17457     * @see #isPaddingOffsetRequired()
17458     *
17459     * @since CURRENT
17460     */
17461    protected int getBottomPaddingOffset() {
17462        return 0;
17463    }
17464
17465    /**
17466     * @hide
17467     * @param offsetRequired
17468     */
17469    protected int getFadeTop(boolean offsetRequired) {
17470        int top = mPaddingTop;
17471        if (offsetRequired) top += getTopPaddingOffset();
17472        return top;
17473    }
17474
17475    /**
17476     * @hide
17477     * @param offsetRequired
17478     */
17479    protected int getFadeHeight(boolean offsetRequired) {
17480        int padding = mPaddingTop;
17481        if (offsetRequired) padding += getTopPaddingOffset();
17482        return mBottom - mTop - mPaddingBottom - padding;
17483    }
17484
17485    /**
17486     * <p>Indicates whether this view is attached to a hardware accelerated
17487     * window or not.</p>
17488     *
17489     * <p>Even if this method returns true, it does not mean that every call
17490     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
17491     * accelerated {@link android.graphics.Canvas}. For instance, if this view
17492     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
17493     * window is hardware accelerated,
17494     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
17495     * return false, and this method will return true.</p>
17496     *
17497     * @return True if the view is attached to a window and the window is
17498     *         hardware accelerated; false in any other case.
17499     */
17500    @ViewDebug.ExportedProperty(category = "drawing")
17501    public boolean isHardwareAccelerated() {
17502        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
17503    }
17504
17505    /**
17506     * Sets a rectangular area on this view to which the view will be clipped
17507     * when it is drawn. Setting the value to null will remove the clip bounds
17508     * and the view will draw normally, using its full bounds.
17509     *
17510     * @param clipBounds The rectangular area, in the local coordinates of
17511     * this view, to which future drawing operations will be clipped.
17512     */
17513    public void setClipBounds(Rect clipBounds) {
17514        if (clipBounds == mClipBounds
17515                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
17516            return;
17517        }
17518        if (clipBounds != null) {
17519            if (mClipBounds == null) {
17520                mClipBounds = new Rect(clipBounds);
17521            } else {
17522                mClipBounds.set(clipBounds);
17523            }
17524        } else {
17525            mClipBounds = null;
17526        }
17527        mRenderNode.setClipBounds(mClipBounds);
17528        invalidateViewProperty(false, false);
17529    }
17530
17531    /**
17532     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
17533     *
17534     * @return A copy of the current clip bounds if clip bounds are set,
17535     * otherwise null.
17536     */
17537    public Rect getClipBounds() {
17538        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
17539    }
17540
17541
17542    /**
17543     * Populates an output rectangle with the clip bounds of the view,
17544     * returning {@code true} if successful or {@code false} if the view's
17545     * clip bounds are {@code null}.
17546     *
17547     * @param outRect rectangle in which to place the clip bounds of the view
17548     * @return {@code true} if successful or {@code false} if the view's
17549     *         clip bounds are {@code null}
17550     */
17551    public boolean getClipBounds(Rect outRect) {
17552        if (mClipBounds != null) {
17553            outRect.set(mClipBounds);
17554            return true;
17555        }
17556        return false;
17557    }
17558
17559    /**
17560     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
17561     * case of an active Animation being run on the view.
17562     */
17563    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
17564            Animation a, boolean scalingRequired) {
17565        Transformation invalidationTransform;
17566        final int flags = parent.mGroupFlags;
17567        final boolean initialized = a.isInitialized();
17568        if (!initialized) {
17569            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
17570            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
17571            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
17572            onAnimationStart();
17573        }
17574
17575        final Transformation t = parent.getChildTransformation();
17576        boolean more = a.getTransformation(drawingTime, t, 1f);
17577        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
17578            if (parent.mInvalidationTransformation == null) {
17579                parent.mInvalidationTransformation = new Transformation();
17580            }
17581            invalidationTransform = parent.mInvalidationTransformation;
17582            a.getTransformation(drawingTime, invalidationTransform, 1f);
17583        } else {
17584            invalidationTransform = t;
17585        }
17586
17587        if (more) {
17588            if (!a.willChangeBounds()) {
17589                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
17590                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
17591                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
17592                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
17593                    // The child need to draw an animation, potentially offscreen, so
17594                    // make sure we do not cancel invalidate requests
17595                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
17596                    parent.invalidate(mLeft, mTop, mRight, mBottom);
17597                }
17598            } else {
17599                if (parent.mInvalidateRegion == null) {
17600                    parent.mInvalidateRegion = new RectF();
17601                }
17602                final RectF region = parent.mInvalidateRegion;
17603                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
17604                        invalidationTransform);
17605
17606                // The child need to draw an animation, potentially offscreen, so
17607                // make sure we do not cancel invalidate requests
17608                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
17609
17610                final int left = mLeft + (int) region.left;
17611                final int top = mTop + (int) region.top;
17612                parent.invalidate(left, top, left + (int) (region.width() + .5f),
17613                        top + (int) (region.height() + .5f));
17614            }
17615        }
17616        return more;
17617    }
17618
17619    /**
17620     * This method is called by getDisplayList() when a display list is recorded for a View.
17621     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
17622     */
17623    void setDisplayListProperties(RenderNode renderNode) {
17624        if (renderNode != null) {
17625            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
17626            renderNode.setClipToBounds(mParent instanceof ViewGroup
17627                    && ((ViewGroup) mParent).getClipChildren());
17628
17629            float alpha = 1;
17630            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
17631                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
17632                ViewGroup parentVG = (ViewGroup) mParent;
17633                final Transformation t = parentVG.getChildTransformation();
17634                if (parentVG.getChildStaticTransformation(this, t)) {
17635                    final int transformType = t.getTransformationType();
17636                    if (transformType != Transformation.TYPE_IDENTITY) {
17637                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
17638                            alpha = t.getAlpha();
17639                        }
17640                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
17641                            renderNode.setStaticMatrix(t.getMatrix());
17642                        }
17643                    }
17644                }
17645            }
17646            if (mTransformationInfo != null) {
17647                alpha *= getFinalAlpha();
17648                if (alpha < 1) {
17649                    final int multipliedAlpha = (int) (255 * alpha);
17650                    if (onSetAlpha(multipliedAlpha)) {
17651                        alpha = 1;
17652                    }
17653                }
17654                renderNode.setAlpha(alpha);
17655            } else if (alpha < 1) {
17656                renderNode.setAlpha(alpha);
17657            }
17658        }
17659    }
17660
17661    /**
17662     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
17663     *
17664     * This is where the View specializes rendering behavior based on layer type,
17665     * and hardware acceleration.
17666     */
17667    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
17668        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
17669        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
17670         *
17671         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
17672         * HW accelerated, it can't handle drawing RenderNodes.
17673         */
17674        boolean drawingWithRenderNode = mAttachInfo != null
17675                && mAttachInfo.mHardwareAccelerated
17676                && hardwareAcceleratedCanvas;
17677
17678        boolean more = false;
17679        final boolean childHasIdentityMatrix = hasIdentityMatrix();
17680        final int parentFlags = parent.mGroupFlags;
17681
17682        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
17683            parent.getChildTransformation().clear();
17684            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17685        }
17686
17687        Transformation transformToApply = null;
17688        boolean concatMatrix = false;
17689        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
17690        final Animation a = getAnimation();
17691        if (a != null) {
17692            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
17693            concatMatrix = a.willChangeTransformationMatrix();
17694            if (concatMatrix) {
17695                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
17696            }
17697            transformToApply = parent.getChildTransformation();
17698        } else {
17699            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
17700                // No longer animating: clear out old animation matrix
17701                mRenderNode.setAnimationMatrix(null);
17702                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
17703            }
17704            if (!drawingWithRenderNode
17705                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
17706                final Transformation t = parent.getChildTransformation();
17707                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
17708                if (hasTransform) {
17709                    final int transformType = t.getTransformationType();
17710                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
17711                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
17712                }
17713            }
17714        }
17715
17716        concatMatrix |= !childHasIdentityMatrix;
17717
17718        // Sets the flag as early as possible to allow draw() implementations
17719        // to call invalidate() successfully when doing animations
17720        mPrivateFlags |= PFLAG_DRAWN;
17721
17722        if (!concatMatrix &&
17723                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
17724                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
17725                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
17726                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
17727            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
17728            return more;
17729        }
17730        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
17731
17732        if (hardwareAcceleratedCanvas) {
17733            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
17734            // retain the flag's value temporarily in the mRecreateDisplayList flag
17735            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
17736            mPrivateFlags &= ~PFLAG_INVALIDATED;
17737        }
17738
17739        RenderNode renderNode = null;
17740        Bitmap cache = null;
17741        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
17742        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
17743             if (layerType != LAYER_TYPE_NONE) {
17744                 // If not drawing with RenderNode, treat HW layers as SW
17745                 layerType = LAYER_TYPE_SOFTWARE;
17746                 buildDrawingCache(true);
17747            }
17748            cache = getDrawingCache(true);
17749        }
17750
17751        if (drawingWithRenderNode) {
17752            // Delay getting the display list until animation-driven alpha values are
17753            // set up and possibly passed on to the view
17754            renderNode = updateDisplayListIfDirty();
17755            if (!renderNode.isValid()) {
17756                // Uncommon, but possible. If a view is removed from the hierarchy during the call
17757                // to getDisplayList(), the display list will be marked invalid and we should not
17758                // try to use it again.
17759                renderNode = null;
17760                drawingWithRenderNode = false;
17761            }
17762        }
17763
17764        int sx = 0;
17765        int sy = 0;
17766        if (!drawingWithRenderNode) {
17767            computeScroll();
17768            sx = mScrollX;
17769            sy = mScrollY;
17770        }
17771
17772        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
17773        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
17774
17775        int restoreTo = -1;
17776        if (!drawingWithRenderNode || transformToApply != null) {
17777            restoreTo = canvas.save();
17778        }
17779        if (offsetForScroll) {
17780            canvas.translate(mLeft - sx, mTop - sy);
17781        } else {
17782            if (!drawingWithRenderNode) {
17783                canvas.translate(mLeft, mTop);
17784            }
17785            if (scalingRequired) {
17786                if (drawingWithRenderNode) {
17787                    // TODO: Might not need this if we put everything inside the DL
17788                    restoreTo = canvas.save();
17789                }
17790                // mAttachInfo cannot be null, otherwise scalingRequired == false
17791                final float scale = 1.0f / mAttachInfo.mApplicationScale;
17792                canvas.scale(scale, scale);
17793            }
17794        }
17795
17796        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
17797        if (transformToApply != null
17798                || alpha < 1
17799                || !hasIdentityMatrix()
17800                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17801            if (transformToApply != null || !childHasIdentityMatrix) {
17802                int transX = 0;
17803                int transY = 0;
17804
17805                if (offsetForScroll) {
17806                    transX = -sx;
17807                    transY = -sy;
17808                }
17809
17810                if (transformToApply != null) {
17811                    if (concatMatrix) {
17812                        if (drawingWithRenderNode) {
17813                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
17814                        } else {
17815                            // Undo the scroll translation, apply the transformation matrix,
17816                            // then redo the scroll translate to get the correct result.
17817                            canvas.translate(-transX, -transY);
17818                            canvas.concat(transformToApply.getMatrix());
17819                            canvas.translate(transX, transY);
17820                        }
17821                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17822                    }
17823
17824                    float transformAlpha = transformToApply.getAlpha();
17825                    if (transformAlpha < 1) {
17826                        alpha *= transformAlpha;
17827                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17828                    }
17829                }
17830
17831                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
17832                    canvas.translate(-transX, -transY);
17833                    canvas.concat(getMatrix());
17834                    canvas.translate(transX, transY);
17835                }
17836            }
17837
17838            // Deal with alpha if it is or used to be <1
17839            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
17840                if (alpha < 1) {
17841                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17842                } else {
17843                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
17844                }
17845                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
17846                if (!drawingWithDrawingCache) {
17847                    final int multipliedAlpha = (int) (255 * alpha);
17848                    if (!onSetAlpha(multipliedAlpha)) {
17849                        if (drawingWithRenderNode) {
17850                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
17851                        } else if (layerType == LAYER_TYPE_NONE) {
17852                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
17853                                    multipliedAlpha);
17854                        }
17855                    } else {
17856                        // Alpha is handled by the child directly, clobber the layer's alpha
17857                        mPrivateFlags |= PFLAG_ALPHA_SET;
17858                    }
17859                }
17860            }
17861        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17862            onSetAlpha(255);
17863            mPrivateFlags &= ~PFLAG_ALPHA_SET;
17864        }
17865
17866        if (!drawingWithRenderNode) {
17867            // apply clips directly, since RenderNode won't do it for this draw
17868            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
17869                if (offsetForScroll) {
17870                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
17871                } else {
17872                    if (!scalingRequired || cache == null) {
17873                        canvas.clipRect(0, 0, getWidth(), getHeight());
17874                    } else {
17875                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
17876                    }
17877                }
17878            }
17879
17880            if (mClipBounds != null) {
17881                // clip bounds ignore scroll
17882                canvas.clipRect(mClipBounds);
17883            }
17884        }
17885
17886        if (!drawingWithDrawingCache) {
17887            if (drawingWithRenderNode) {
17888                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17889                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
17890            } else {
17891                // Fast path for layouts with no backgrounds
17892                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17893                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17894                    dispatchDraw(canvas);
17895                } else {
17896                    draw(canvas);
17897                }
17898            }
17899        } else if (cache != null) {
17900            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17901            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
17902                // no layer paint, use temporary paint to draw bitmap
17903                Paint cachePaint = parent.mCachePaint;
17904                if (cachePaint == null) {
17905                    cachePaint = new Paint();
17906                    cachePaint.setDither(false);
17907                    parent.mCachePaint = cachePaint;
17908                }
17909                cachePaint.setAlpha((int) (alpha * 255));
17910                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
17911            } else {
17912                // use layer paint to draw the bitmap, merging the two alphas, but also restore
17913                int layerPaintAlpha = mLayerPaint.getAlpha();
17914                if (alpha < 1) {
17915                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
17916                }
17917                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
17918                if (alpha < 1) {
17919                    mLayerPaint.setAlpha(layerPaintAlpha);
17920                }
17921            }
17922        }
17923
17924        if (restoreTo >= 0) {
17925            canvas.restoreToCount(restoreTo);
17926        }
17927
17928        if (a != null && !more) {
17929            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
17930                onSetAlpha(255);
17931            }
17932            parent.finishAnimatingView(this, a);
17933        }
17934
17935        if (more && hardwareAcceleratedCanvas) {
17936            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
17937                // alpha animations should cause the child to recreate its display list
17938                invalidate(true);
17939            }
17940        }
17941
17942        mRecreateDisplayList = false;
17943
17944        return more;
17945    }
17946
17947    static Paint getDebugPaint() {
17948        if (sDebugPaint == null) {
17949            sDebugPaint = new Paint();
17950            sDebugPaint.setAntiAlias(false);
17951        }
17952        return sDebugPaint;
17953    }
17954
17955    final int dipsToPixels(int dips) {
17956        float scale = getContext().getResources().getDisplayMetrics().density;
17957        return (int) (dips * scale + 0.5f);
17958    }
17959
17960    final private void debugDrawFocus(Canvas canvas) {
17961        if (isFocused()) {
17962            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
17963            final int l = mScrollX;
17964            final int r = l + mRight - mLeft;
17965            final int t = mScrollY;
17966            final int b = t + mBottom - mTop;
17967
17968            final Paint paint = getDebugPaint();
17969            paint.setColor(DEBUG_CORNERS_COLOR);
17970
17971            // Draw squares in corners.
17972            paint.setStyle(Paint.Style.FILL);
17973            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
17974            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
17975            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
17976            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
17977
17978            // Draw big X across the view.
17979            paint.setStyle(Paint.Style.STROKE);
17980            canvas.drawLine(l, t, r, b, paint);
17981            canvas.drawLine(l, b, r, t, paint);
17982        }
17983    }
17984
17985    /**
17986     * Manually render this view (and all of its children) to the given Canvas.
17987     * The view must have already done a full layout before this function is
17988     * called.  When implementing a view, implement
17989     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
17990     * If you do need to override this method, call the superclass version.
17991     *
17992     * @param canvas The Canvas to which the View is rendered.
17993     */
17994    @CallSuper
17995    public void draw(Canvas canvas) {
17996        final int privateFlags = mPrivateFlags;
17997        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
17998                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
17999        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
18000
18001        /*
18002         * Draw traversal performs several drawing steps which must be executed
18003         * in the appropriate order:
18004         *
18005         *      1. Draw the background
18006         *      2. If necessary, save the canvas' layers to prepare for fading
18007         *      3. Draw view's content
18008         *      4. Draw children
18009         *      5. If necessary, draw the fading edges and restore layers
18010         *      6. Draw decorations (scrollbars for instance)
18011         */
18012
18013        // Step 1, draw the background, if needed
18014        int saveCount;
18015
18016        if (!dirtyOpaque) {
18017            drawBackground(canvas);
18018        }
18019
18020        // skip step 2 & 5 if possible (common case)
18021        final int viewFlags = mViewFlags;
18022        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
18023        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
18024        if (!verticalEdges && !horizontalEdges) {
18025            // Step 3, draw the content
18026            if (!dirtyOpaque) onDraw(canvas);
18027
18028            // Step 4, draw the children
18029            dispatchDraw(canvas);
18030
18031            // Overlay is part of the content and draws beneath Foreground
18032            if (mOverlay != null && !mOverlay.isEmpty()) {
18033                mOverlay.getOverlayView().dispatchDraw(canvas);
18034            }
18035
18036            // Step 6, draw decorations (foreground, scrollbars)
18037            onDrawForeground(canvas);
18038
18039            if (debugDraw()) {
18040                debugDrawFocus(canvas);
18041            }
18042
18043            // we're done...
18044            return;
18045        }
18046
18047        /*
18048         * Here we do the full fledged routine...
18049         * (this is an uncommon case where speed matters less,
18050         * this is why we repeat some of the tests that have been
18051         * done above)
18052         */
18053
18054        boolean drawTop = false;
18055        boolean drawBottom = false;
18056        boolean drawLeft = false;
18057        boolean drawRight = false;
18058
18059        float topFadeStrength = 0.0f;
18060        float bottomFadeStrength = 0.0f;
18061        float leftFadeStrength = 0.0f;
18062        float rightFadeStrength = 0.0f;
18063
18064        // Step 2, save the canvas' layers
18065        int paddingLeft = mPaddingLeft;
18066
18067        final boolean offsetRequired = isPaddingOffsetRequired();
18068        if (offsetRequired) {
18069            paddingLeft += getLeftPaddingOffset();
18070        }
18071
18072        int left = mScrollX + paddingLeft;
18073        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
18074        int top = mScrollY + getFadeTop(offsetRequired);
18075        int bottom = top + getFadeHeight(offsetRequired);
18076
18077        if (offsetRequired) {
18078            right += getRightPaddingOffset();
18079            bottom += getBottomPaddingOffset();
18080        }
18081
18082        final ScrollabilityCache scrollabilityCache = mScrollCache;
18083        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
18084        int length = (int) fadeHeight;
18085
18086        // clip the fade length if top and bottom fades overlap
18087        // overlapping fades produce odd-looking artifacts
18088        if (verticalEdges && (top + length > bottom - length)) {
18089            length = (bottom - top) / 2;
18090        }
18091
18092        // also clip horizontal fades if necessary
18093        if (horizontalEdges && (left + length > right - length)) {
18094            length = (right - left) / 2;
18095        }
18096
18097        if (verticalEdges) {
18098            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
18099            drawTop = topFadeStrength * fadeHeight > 1.0f;
18100            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
18101            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
18102        }
18103
18104        if (horizontalEdges) {
18105            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
18106            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
18107            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
18108            drawRight = rightFadeStrength * fadeHeight > 1.0f;
18109        }
18110
18111        saveCount = canvas.getSaveCount();
18112
18113        int solidColor = getSolidColor();
18114        if (solidColor == 0) {
18115            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
18116
18117            if (drawTop) {
18118                canvas.saveLayer(left, top, right, top + length, null, flags);
18119            }
18120
18121            if (drawBottom) {
18122                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
18123            }
18124
18125            if (drawLeft) {
18126                canvas.saveLayer(left, top, left + length, bottom, null, flags);
18127            }
18128
18129            if (drawRight) {
18130                canvas.saveLayer(right - length, top, right, bottom, null, flags);
18131            }
18132        } else {
18133            scrollabilityCache.setFadeColor(solidColor);
18134        }
18135
18136        // Step 3, draw the content
18137        if (!dirtyOpaque) onDraw(canvas);
18138
18139        // Step 4, draw the children
18140        dispatchDraw(canvas);
18141
18142        // Step 5, draw the fade effect and restore layers
18143        final Paint p = scrollabilityCache.paint;
18144        final Matrix matrix = scrollabilityCache.matrix;
18145        final Shader fade = scrollabilityCache.shader;
18146
18147        if (drawTop) {
18148            matrix.setScale(1, fadeHeight * topFadeStrength);
18149            matrix.postTranslate(left, top);
18150            fade.setLocalMatrix(matrix);
18151            p.setShader(fade);
18152            canvas.drawRect(left, top, right, top + length, p);
18153        }
18154
18155        if (drawBottom) {
18156            matrix.setScale(1, fadeHeight * bottomFadeStrength);
18157            matrix.postRotate(180);
18158            matrix.postTranslate(left, bottom);
18159            fade.setLocalMatrix(matrix);
18160            p.setShader(fade);
18161            canvas.drawRect(left, bottom - length, right, bottom, p);
18162        }
18163
18164        if (drawLeft) {
18165            matrix.setScale(1, fadeHeight * leftFadeStrength);
18166            matrix.postRotate(-90);
18167            matrix.postTranslate(left, top);
18168            fade.setLocalMatrix(matrix);
18169            p.setShader(fade);
18170            canvas.drawRect(left, top, left + length, bottom, p);
18171        }
18172
18173        if (drawRight) {
18174            matrix.setScale(1, fadeHeight * rightFadeStrength);
18175            matrix.postRotate(90);
18176            matrix.postTranslate(right, top);
18177            fade.setLocalMatrix(matrix);
18178            p.setShader(fade);
18179            canvas.drawRect(right - length, top, right, bottom, p);
18180        }
18181
18182        canvas.restoreToCount(saveCount);
18183
18184        // Overlay is part of the content and draws beneath Foreground
18185        if (mOverlay != null && !mOverlay.isEmpty()) {
18186            mOverlay.getOverlayView().dispatchDraw(canvas);
18187        }
18188
18189        // Step 6, draw decorations (foreground, scrollbars)
18190        onDrawForeground(canvas);
18191
18192        if (debugDraw()) {
18193            debugDrawFocus(canvas);
18194        }
18195    }
18196
18197    /**
18198     * Draws the background onto the specified canvas.
18199     *
18200     * @param canvas Canvas on which to draw the background
18201     */
18202    private void drawBackground(Canvas canvas) {
18203        final Drawable background = mBackground;
18204        if (background == null) {
18205            return;
18206        }
18207
18208        setBackgroundBounds();
18209
18210        // Attempt to use a display list if requested.
18211        if (canvas.isHardwareAccelerated() && mAttachInfo != null
18212                && mAttachInfo.mThreadedRenderer != null) {
18213            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
18214
18215            final RenderNode renderNode = mBackgroundRenderNode;
18216            if (renderNode != null && renderNode.isValid()) {
18217                setBackgroundRenderNodeProperties(renderNode);
18218                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18219                return;
18220            }
18221        }
18222
18223        final int scrollX = mScrollX;
18224        final int scrollY = mScrollY;
18225        if ((scrollX | scrollY) == 0) {
18226            background.draw(canvas);
18227        } else {
18228            canvas.translate(scrollX, scrollY);
18229            background.draw(canvas);
18230            canvas.translate(-scrollX, -scrollY);
18231        }
18232    }
18233
18234    /**
18235     * Sets the correct background bounds and rebuilds the outline, if needed.
18236     * <p/>
18237     * This is called by LayoutLib.
18238     */
18239    void setBackgroundBounds() {
18240        if (mBackgroundSizeChanged && mBackground != null) {
18241            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
18242            mBackgroundSizeChanged = false;
18243            rebuildOutline();
18244        }
18245    }
18246
18247    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
18248        renderNode.setTranslationX(mScrollX);
18249        renderNode.setTranslationY(mScrollY);
18250    }
18251
18252    /**
18253     * Creates a new display list or updates the existing display list for the
18254     * specified Drawable.
18255     *
18256     * @param drawable Drawable for which to create a display list
18257     * @param renderNode Existing RenderNode, or {@code null}
18258     * @return A valid display list for the specified drawable
18259     */
18260    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
18261        if (renderNode == null) {
18262            renderNode = RenderNode.create(drawable.getClass().getName(), this);
18263        }
18264
18265        final Rect bounds = drawable.getBounds();
18266        final int width = bounds.width();
18267        final int height = bounds.height();
18268        final DisplayListCanvas canvas = renderNode.start(width, height);
18269
18270        // Reverse left/top translation done by drawable canvas, which will
18271        // instead be applied by rendernode's LTRB bounds below. This way, the
18272        // drawable's bounds match with its rendernode bounds and its content
18273        // will lie within those bounds in the rendernode tree.
18274        canvas.translate(-bounds.left, -bounds.top);
18275
18276        try {
18277            drawable.draw(canvas);
18278        } finally {
18279            renderNode.end(canvas);
18280        }
18281
18282        // Set up drawable properties that are view-independent.
18283        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
18284        renderNode.setProjectBackwards(drawable.isProjected());
18285        renderNode.setProjectionReceiver(true);
18286        renderNode.setClipToBounds(false);
18287        return renderNode;
18288    }
18289
18290    /**
18291     * Returns the overlay for this view, creating it if it does not yet exist.
18292     * Adding drawables to the overlay will cause them to be displayed whenever
18293     * the view itself is redrawn. Objects in the overlay should be actively
18294     * managed: remove them when they should not be displayed anymore. The
18295     * overlay will always have the same size as its host view.
18296     *
18297     * <p>Note: Overlays do not currently work correctly with {@link
18298     * SurfaceView} or {@link TextureView}; contents in overlays for these
18299     * types of views may not display correctly.</p>
18300     *
18301     * @return The ViewOverlay object for this view.
18302     * @see ViewOverlay
18303     */
18304    public ViewOverlay getOverlay() {
18305        if (mOverlay == null) {
18306            mOverlay = new ViewOverlay(mContext, this);
18307        }
18308        return mOverlay;
18309    }
18310
18311    /**
18312     * Override this if your view is known to always be drawn on top of a solid color background,
18313     * and needs to draw fading edges. Returning a non-zero color enables the view system to
18314     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
18315     * should be set to 0xFF.
18316     *
18317     * @see #setVerticalFadingEdgeEnabled(boolean)
18318     * @see #setHorizontalFadingEdgeEnabled(boolean)
18319     *
18320     * @return The known solid color background for this view, or 0 if the color may vary
18321     */
18322    @ViewDebug.ExportedProperty(category = "drawing")
18323    @ColorInt
18324    public int getSolidColor() {
18325        return 0;
18326    }
18327
18328    /**
18329     * Build a human readable string representation of the specified view flags.
18330     *
18331     * @param flags the view flags to convert to a string
18332     * @return a String representing the supplied flags
18333     */
18334    private static String printFlags(int flags) {
18335        String output = "";
18336        int numFlags = 0;
18337        if ((flags & FOCUSABLE) == FOCUSABLE) {
18338            output += "TAKES_FOCUS";
18339            numFlags++;
18340        }
18341
18342        switch (flags & VISIBILITY_MASK) {
18343        case INVISIBLE:
18344            if (numFlags > 0) {
18345                output += " ";
18346            }
18347            output += "INVISIBLE";
18348            // USELESS HERE numFlags++;
18349            break;
18350        case GONE:
18351            if (numFlags > 0) {
18352                output += " ";
18353            }
18354            output += "GONE";
18355            // USELESS HERE numFlags++;
18356            break;
18357        default:
18358            break;
18359        }
18360        return output;
18361    }
18362
18363    /**
18364     * Build a human readable string representation of the specified private
18365     * view flags.
18366     *
18367     * @param privateFlags the private view flags to convert to a string
18368     * @return a String representing the supplied flags
18369     */
18370    private static String printPrivateFlags(int privateFlags) {
18371        String output = "";
18372        int numFlags = 0;
18373
18374        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
18375            output += "WANTS_FOCUS";
18376            numFlags++;
18377        }
18378
18379        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
18380            if (numFlags > 0) {
18381                output += " ";
18382            }
18383            output += "FOCUSED";
18384            numFlags++;
18385        }
18386
18387        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
18388            if (numFlags > 0) {
18389                output += " ";
18390            }
18391            output += "SELECTED";
18392            numFlags++;
18393        }
18394
18395        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
18396            if (numFlags > 0) {
18397                output += " ";
18398            }
18399            output += "IS_ROOT_NAMESPACE";
18400            numFlags++;
18401        }
18402
18403        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
18404            if (numFlags > 0) {
18405                output += " ";
18406            }
18407            output += "HAS_BOUNDS";
18408            numFlags++;
18409        }
18410
18411        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
18412            if (numFlags > 0) {
18413                output += " ";
18414            }
18415            output += "DRAWN";
18416            // USELESS HERE numFlags++;
18417        }
18418        return output;
18419    }
18420
18421    /**
18422     * <p>Indicates whether or not this view's layout will be requested during
18423     * the next hierarchy layout pass.</p>
18424     *
18425     * @return true if the layout will be forced during next layout pass
18426     */
18427    public boolean isLayoutRequested() {
18428        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
18429    }
18430
18431    /**
18432     * Return true if o is a ViewGroup that is laying out using optical bounds.
18433     * @hide
18434     */
18435    public static boolean isLayoutModeOptical(Object o) {
18436        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
18437    }
18438
18439    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
18440        Insets parentInsets = mParent instanceof View ?
18441                ((View) mParent).getOpticalInsets() : Insets.NONE;
18442        Insets childInsets = getOpticalInsets();
18443        return setFrame(
18444                left   + parentInsets.left - childInsets.left,
18445                top    + parentInsets.top  - childInsets.top,
18446                right  + parentInsets.left + childInsets.right,
18447                bottom + parentInsets.top  + childInsets.bottom);
18448    }
18449
18450    /**
18451     * Assign a size and position to a view and all of its
18452     * descendants
18453     *
18454     * <p>This is the second phase of the layout mechanism.
18455     * (The first is measuring). In this phase, each parent calls
18456     * layout on all of its children to position them.
18457     * This is typically done using the child measurements
18458     * that were stored in the measure pass().</p>
18459     *
18460     * <p>Derived classes should not override this method.
18461     * Derived classes with children should override
18462     * onLayout. In that method, they should
18463     * call layout on each of their children.</p>
18464     *
18465     * @param l Left position, relative to parent
18466     * @param t Top position, relative to parent
18467     * @param r Right position, relative to parent
18468     * @param b Bottom position, relative to parent
18469     */
18470    @SuppressWarnings({"unchecked"})
18471    public void layout(int l, int t, int r, int b) {
18472        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
18473            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
18474            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18475        }
18476
18477        int oldL = mLeft;
18478        int oldT = mTop;
18479        int oldB = mBottom;
18480        int oldR = mRight;
18481
18482        boolean changed = isLayoutModeOptical(mParent) ?
18483                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
18484
18485        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
18486            onLayout(changed, l, t, r, b);
18487
18488            if (shouldDrawRoundScrollbar()) {
18489                if(mRoundScrollbarRenderer == null) {
18490                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
18491                }
18492            } else {
18493                mRoundScrollbarRenderer = null;
18494            }
18495
18496            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
18497
18498            ListenerInfo li = mListenerInfo;
18499            if (li != null && li.mOnLayoutChangeListeners != null) {
18500                ArrayList<OnLayoutChangeListener> listenersCopy =
18501                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
18502                int numListeners = listenersCopy.size();
18503                for (int i = 0; i < numListeners; ++i) {
18504                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
18505                }
18506            }
18507        }
18508
18509        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
18510        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
18511    }
18512
18513    /**
18514     * Called from layout when this view should
18515     * assign a size and position to each of its children.
18516     *
18517     * Derived classes with children should override
18518     * this method and call layout on each of
18519     * their children.
18520     * @param changed This is a new size or position for this view
18521     * @param left Left position, relative to parent
18522     * @param top Top position, relative to parent
18523     * @param right Right position, relative to parent
18524     * @param bottom Bottom position, relative to parent
18525     */
18526    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
18527    }
18528
18529    /**
18530     * Assign a size and position to this view.
18531     *
18532     * This is called from layout.
18533     *
18534     * @param left Left position, relative to parent
18535     * @param top Top position, relative to parent
18536     * @param right Right position, relative to parent
18537     * @param bottom Bottom position, relative to parent
18538     * @return true if the new size and position are different than the
18539     *         previous ones
18540     * {@hide}
18541     */
18542    protected boolean setFrame(int left, int top, int right, int bottom) {
18543        boolean changed = false;
18544
18545        if (DBG) {
18546            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
18547                    + right + "," + bottom + ")");
18548        }
18549
18550        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
18551            changed = true;
18552
18553            // Remember our drawn bit
18554            int drawn = mPrivateFlags & PFLAG_DRAWN;
18555
18556            int oldWidth = mRight - mLeft;
18557            int oldHeight = mBottom - mTop;
18558            int newWidth = right - left;
18559            int newHeight = bottom - top;
18560            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
18561
18562            // Invalidate our old position
18563            invalidate(sizeChanged);
18564
18565            mLeft = left;
18566            mTop = top;
18567            mRight = right;
18568            mBottom = bottom;
18569            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
18570
18571            mPrivateFlags |= PFLAG_HAS_BOUNDS;
18572
18573
18574            if (sizeChanged) {
18575                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
18576            }
18577
18578            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
18579                // If we are visible, force the DRAWN bit to on so that
18580                // this invalidate will go through (at least to our parent).
18581                // This is because someone may have invalidated this view
18582                // before this call to setFrame came in, thereby clearing
18583                // the DRAWN bit.
18584                mPrivateFlags |= PFLAG_DRAWN;
18585                invalidate(sizeChanged);
18586                // parent display list may need to be recreated based on a change in the bounds
18587                // of any child
18588                invalidateParentCaches();
18589            }
18590
18591            // Reset drawn bit to original value (invalidate turns it off)
18592            mPrivateFlags |= drawn;
18593
18594            mBackgroundSizeChanged = true;
18595            if (mForegroundInfo != null) {
18596                mForegroundInfo.mBoundsChanged = true;
18597            }
18598
18599            notifySubtreeAccessibilityStateChangedIfNeeded();
18600        }
18601        return changed;
18602    }
18603
18604    /**
18605     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
18606     * @hide
18607     */
18608    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
18609        setFrame(left, top, right, bottom);
18610    }
18611
18612    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
18613        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
18614        if (mOverlay != null) {
18615            mOverlay.getOverlayView().setRight(newWidth);
18616            mOverlay.getOverlayView().setBottom(newHeight);
18617        }
18618        rebuildOutline();
18619    }
18620
18621    /**
18622     * Finalize inflating a view from XML.  This is called as the last phase
18623     * of inflation, after all child views have been added.
18624     *
18625     * <p>Even if the subclass overrides onFinishInflate, they should always be
18626     * sure to call the super method, so that we get called.
18627     */
18628    @CallSuper
18629    protected void onFinishInflate() {
18630    }
18631
18632    /**
18633     * Returns the resources associated with this view.
18634     *
18635     * @return Resources object.
18636     */
18637    public Resources getResources() {
18638        return mResources;
18639    }
18640
18641    /**
18642     * Invalidates the specified Drawable.
18643     *
18644     * @param drawable the drawable to invalidate
18645     */
18646    @Override
18647    public void invalidateDrawable(@NonNull Drawable drawable) {
18648        if (verifyDrawable(drawable)) {
18649            final Rect dirty = drawable.getDirtyBounds();
18650            final int scrollX = mScrollX;
18651            final int scrollY = mScrollY;
18652
18653            invalidate(dirty.left + scrollX, dirty.top + scrollY,
18654                    dirty.right + scrollX, dirty.bottom + scrollY);
18655            rebuildOutline();
18656        }
18657    }
18658
18659    /**
18660     * Schedules an action on a drawable to occur at a specified time.
18661     *
18662     * @param who the recipient of the action
18663     * @param what the action to run on the drawable
18664     * @param when the time at which the action must occur. Uses the
18665     *        {@link SystemClock#uptimeMillis} timebase.
18666     */
18667    @Override
18668    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
18669        if (verifyDrawable(who) && what != null) {
18670            final long delay = when - SystemClock.uptimeMillis();
18671            if (mAttachInfo != null) {
18672                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
18673                        Choreographer.CALLBACK_ANIMATION, what, who,
18674                        Choreographer.subtractFrameDelay(delay));
18675            } else {
18676                // Postpone the runnable until we know
18677                // on which thread it needs to run.
18678                getRunQueue().postDelayed(what, delay);
18679            }
18680        }
18681    }
18682
18683    /**
18684     * Cancels a scheduled action on a drawable.
18685     *
18686     * @param who the recipient of the action
18687     * @param what the action to cancel
18688     */
18689    @Override
18690    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
18691        if (verifyDrawable(who) && what != null) {
18692            if (mAttachInfo != null) {
18693                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
18694                        Choreographer.CALLBACK_ANIMATION, what, who);
18695            }
18696            getRunQueue().removeCallbacks(what);
18697        }
18698    }
18699
18700    /**
18701     * Unschedule any events associated with the given Drawable.  This can be
18702     * used when selecting a new Drawable into a view, so that the previous
18703     * one is completely unscheduled.
18704     *
18705     * @param who The Drawable to unschedule.
18706     *
18707     * @see #drawableStateChanged
18708     */
18709    public void unscheduleDrawable(Drawable who) {
18710        if (mAttachInfo != null && who != null) {
18711            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
18712                    Choreographer.CALLBACK_ANIMATION, null, who);
18713        }
18714    }
18715
18716    /**
18717     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
18718     * that the View directionality can and will be resolved before its Drawables.
18719     *
18720     * Will call {@link View#onResolveDrawables} when resolution is done.
18721     *
18722     * @hide
18723     */
18724    protected void resolveDrawables() {
18725        // Drawables resolution may need to happen before resolving the layout direction (which is
18726        // done only during the measure() call).
18727        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
18728        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
18729        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
18730        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
18731        // direction to be resolved as its resolved value will be the same as its raw value.
18732        if (!isLayoutDirectionResolved() &&
18733                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
18734            return;
18735        }
18736
18737        final int layoutDirection = isLayoutDirectionResolved() ?
18738                getLayoutDirection() : getRawLayoutDirection();
18739
18740        if (mBackground != null) {
18741            mBackground.setLayoutDirection(layoutDirection);
18742        }
18743        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18744            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
18745        }
18746        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
18747        onResolveDrawables(layoutDirection);
18748    }
18749
18750    boolean areDrawablesResolved() {
18751        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
18752    }
18753
18754    /**
18755     * Called when layout direction has been resolved.
18756     *
18757     * The default implementation does nothing.
18758     *
18759     * @param layoutDirection The resolved layout direction.
18760     *
18761     * @see #LAYOUT_DIRECTION_LTR
18762     * @see #LAYOUT_DIRECTION_RTL
18763     *
18764     * @hide
18765     */
18766    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
18767    }
18768
18769    /**
18770     * @hide
18771     */
18772    protected void resetResolvedDrawables() {
18773        resetResolvedDrawablesInternal();
18774    }
18775
18776    void resetResolvedDrawablesInternal() {
18777        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
18778    }
18779
18780    /**
18781     * If your view subclass is displaying its own Drawable objects, it should
18782     * override this function and return true for any Drawable it is
18783     * displaying.  This allows animations for those drawables to be
18784     * scheduled.
18785     *
18786     * <p>Be sure to call through to the super class when overriding this
18787     * function.
18788     *
18789     * @param who The Drawable to verify.  Return true if it is one you are
18790     *            displaying, else return the result of calling through to the
18791     *            super class.
18792     *
18793     * @return boolean If true than the Drawable is being displayed in the
18794     *         view; else false and it is not allowed to animate.
18795     *
18796     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
18797     * @see #drawableStateChanged()
18798     */
18799    @CallSuper
18800    protected boolean verifyDrawable(@NonNull Drawable who) {
18801        // Avoid verifying the scroll bar drawable so that we don't end up in
18802        // an invalidation loop. This effectively prevents the scroll bar
18803        // drawable from triggering invalidations and scheduling runnables.
18804        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
18805    }
18806
18807    /**
18808     * This function is called whenever the state of the view changes in such
18809     * a way that it impacts the state of drawables being shown.
18810     * <p>
18811     * If the View has a StateListAnimator, it will also be called to run necessary state
18812     * change animations.
18813     * <p>
18814     * Be sure to call through to the superclass when overriding this function.
18815     *
18816     * @see Drawable#setState(int[])
18817     */
18818    @CallSuper
18819    protected void drawableStateChanged() {
18820        final int[] state = getDrawableState();
18821        boolean changed = false;
18822
18823        final Drawable bg = mBackground;
18824        if (bg != null && bg.isStateful()) {
18825            changed |= bg.setState(state);
18826        }
18827
18828        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18829        if (fg != null && fg.isStateful()) {
18830            changed |= fg.setState(state);
18831        }
18832
18833        if (mScrollCache != null) {
18834            final Drawable scrollBar = mScrollCache.scrollBar;
18835            if (scrollBar != null && scrollBar.isStateful()) {
18836                changed |= scrollBar.setState(state)
18837                        && mScrollCache.state != ScrollabilityCache.OFF;
18838            }
18839        }
18840
18841        if (mStateListAnimator != null) {
18842            mStateListAnimator.setState(state);
18843        }
18844
18845        if (changed) {
18846            invalidate();
18847        }
18848    }
18849
18850    /**
18851     * This function is called whenever the view hotspot changes and needs to
18852     * be propagated to drawables or child views managed by the view.
18853     * <p>
18854     * Dispatching to child views is handled by
18855     * {@link #dispatchDrawableHotspotChanged(float, float)}.
18856     * <p>
18857     * Be sure to call through to the superclass when overriding this function.
18858     *
18859     * @param x hotspot x coordinate
18860     * @param y hotspot y coordinate
18861     */
18862    @CallSuper
18863    public void drawableHotspotChanged(float x, float y) {
18864        if (mBackground != null) {
18865            mBackground.setHotspot(x, y);
18866        }
18867        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
18868            mForegroundInfo.mDrawable.setHotspot(x, y);
18869        }
18870
18871        dispatchDrawableHotspotChanged(x, y);
18872    }
18873
18874    /**
18875     * Dispatches drawableHotspotChanged to all of this View's children.
18876     *
18877     * @param x hotspot x coordinate
18878     * @param y hotspot y coordinate
18879     * @see #drawableHotspotChanged(float, float)
18880     */
18881    public void dispatchDrawableHotspotChanged(float x, float y) {
18882    }
18883
18884    /**
18885     * Call this to force a view to update its drawable state. This will cause
18886     * drawableStateChanged to be called on this view. Views that are interested
18887     * in the new state should call getDrawableState.
18888     *
18889     * @see #drawableStateChanged
18890     * @see #getDrawableState
18891     */
18892    public void refreshDrawableState() {
18893        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
18894        drawableStateChanged();
18895
18896        ViewParent parent = mParent;
18897        if (parent != null) {
18898            parent.childDrawableStateChanged(this);
18899        }
18900    }
18901
18902    /**
18903     * Return an array of resource IDs of the drawable states representing the
18904     * current state of the view.
18905     *
18906     * @return The current drawable state
18907     *
18908     * @see Drawable#setState(int[])
18909     * @see #drawableStateChanged()
18910     * @see #onCreateDrawableState(int)
18911     */
18912    public final int[] getDrawableState() {
18913        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
18914            return mDrawableState;
18915        } else {
18916            mDrawableState = onCreateDrawableState(0);
18917            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
18918            return mDrawableState;
18919        }
18920    }
18921
18922    /**
18923     * Generate the new {@link android.graphics.drawable.Drawable} state for
18924     * this view. This is called by the view
18925     * system when the cached Drawable state is determined to be invalid.  To
18926     * retrieve the current state, you should use {@link #getDrawableState}.
18927     *
18928     * @param extraSpace if non-zero, this is the number of extra entries you
18929     * would like in the returned array in which you can place your own
18930     * states.
18931     *
18932     * @return Returns an array holding the current {@link Drawable} state of
18933     * the view.
18934     *
18935     * @see #mergeDrawableStates(int[], int[])
18936     */
18937    protected int[] onCreateDrawableState(int extraSpace) {
18938        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
18939                mParent instanceof View) {
18940            return ((View) mParent).onCreateDrawableState(extraSpace);
18941        }
18942
18943        int[] drawableState;
18944
18945        int privateFlags = mPrivateFlags;
18946
18947        int viewStateIndex = 0;
18948        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
18949        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
18950        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
18951        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
18952        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
18953        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
18954        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
18955                ThreadedRenderer.isAvailable()) {
18956            // This is set if HW acceleration is requested, even if the current
18957            // process doesn't allow it.  This is just to allow app preview
18958            // windows to better match their app.
18959            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
18960        }
18961        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
18962
18963        final int privateFlags2 = mPrivateFlags2;
18964        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
18965            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
18966        }
18967        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
18968            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
18969        }
18970
18971        drawableState = StateSet.get(viewStateIndex);
18972
18973        //noinspection ConstantIfStatement
18974        if (false) {
18975            Log.i("View", "drawableStateIndex=" + viewStateIndex);
18976            Log.i("View", toString()
18977                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
18978                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
18979                    + " fo=" + hasFocus()
18980                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
18981                    + " wf=" + hasWindowFocus()
18982                    + ": " + Arrays.toString(drawableState));
18983        }
18984
18985        if (extraSpace == 0) {
18986            return drawableState;
18987        }
18988
18989        final int[] fullState;
18990        if (drawableState != null) {
18991            fullState = new int[drawableState.length + extraSpace];
18992            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
18993        } else {
18994            fullState = new int[extraSpace];
18995        }
18996
18997        return fullState;
18998    }
18999
19000    /**
19001     * Merge your own state values in <var>additionalState</var> into the base
19002     * state values <var>baseState</var> that were returned by
19003     * {@link #onCreateDrawableState(int)}.
19004     *
19005     * @param baseState The base state values returned by
19006     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
19007     * own additional state values.
19008     *
19009     * @param additionalState The additional state values you would like
19010     * added to <var>baseState</var>; this array is not modified.
19011     *
19012     * @return As a convenience, the <var>baseState</var> array you originally
19013     * passed into the function is returned.
19014     *
19015     * @see #onCreateDrawableState(int)
19016     */
19017    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
19018        final int N = baseState.length;
19019        int i = N - 1;
19020        while (i >= 0 && baseState[i] == 0) {
19021            i--;
19022        }
19023        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
19024        return baseState;
19025    }
19026
19027    /**
19028     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
19029     * on all Drawable objects associated with this view.
19030     * <p>
19031     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
19032     * attached to this view.
19033     */
19034    @CallSuper
19035    public void jumpDrawablesToCurrentState() {
19036        if (mBackground != null) {
19037            mBackground.jumpToCurrentState();
19038        }
19039        if (mStateListAnimator != null) {
19040            mStateListAnimator.jumpToCurrentState();
19041        }
19042        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19043            mForegroundInfo.mDrawable.jumpToCurrentState();
19044        }
19045    }
19046
19047    /**
19048     * Sets the background color for this view.
19049     * @param color the color of the background
19050     */
19051    @RemotableViewMethod
19052    public void setBackgroundColor(@ColorInt int color) {
19053        if (mBackground instanceof ColorDrawable) {
19054            ((ColorDrawable) mBackground.mutate()).setColor(color);
19055            computeOpaqueFlags();
19056            mBackgroundResource = 0;
19057        } else {
19058            setBackground(new ColorDrawable(color));
19059        }
19060    }
19061
19062    /**
19063     * Set the background to a given resource. The resource should refer to
19064     * a Drawable object or 0 to remove the background.
19065     * @param resid The identifier of the resource.
19066     *
19067     * @attr ref android.R.styleable#View_background
19068     */
19069    @RemotableViewMethod
19070    public void setBackgroundResource(@DrawableRes int resid) {
19071        if (resid != 0 && resid == mBackgroundResource) {
19072            return;
19073        }
19074
19075        Drawable d = null;
19076        if (resid != 0) {
19077            d = mContext.getDrawable(resid);
19078        }
19079        setBackground(d);
19080
19081        mBackgroundResource = resid;
19082    }
19083
19084    /**
19085     * Set the background to a given Drawable, or remove the background. If the
19086     * background has padding, this View's padding is set to the background's
19087     * padding. However, when a background is removed, this View's padding isn't
19088     * touched. If setting the padding is desired, please use
19089     * {@link #setPadding(int, int, int, int)}.
19090     *
19091     * @param background The Drawable to use as the background, or null to remove the
19092     *        background
19093     */
19094    public void setBackground(Drawable background) {
19095        //noinspection deprecation
19096        setBackgroundDrawable(background);
19097    }
19098
19099    /**
19100     * @deprecated use {@link #setBackground(Drawable)} instead
19101     */
19102    @Deprecated
19103    public void setBackgroundDrawable(Drawable background) {
19104        computeOpaqueFlags();
19105
19106        if (background == mBackground) {
19107            return;
19108        }
19109
19110        boolean requestLayout = false;
19111
19112        mBackgroundResource = 0;
19113
19114        /*
19115         * Regardless of whether we're setting a new background or not, we want
19116         * to clear the previous drawable. setVisible first while we still have the callback set.
19117         */
19118        if (mBackground != null) {
19119            if (isAttachedToWindow()) {
19120                mBackground.setVisible(false, false);
19121            }
19122            mBackground.setCallback(null);
19123            unscheduleDrawable(mBackground);
19124        }
19125
19126        if (background != null) {
19127            Rect padding = sThreadLocal.get();
19128            if (padding == null) {
19129                padding = new Rect();
19130                sThreadLocal.set(padding);
19131            }
19132            resetResolvedDrawablesInternal();
19133            background.setLayoutDirection(getLayoutDirection());
19134            if (background.getPadding(padding)) {
19135                resetResolvedPaddingInternal();
19136                switch (background.getLayoutDirection()) {
19137                    case LAYOUT_DIRECTION_RTL:
19138                        mUserPaddingLeftInitial = padding.right;
19139                        mUserPaddingRightInitial = padding.left;
19140                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
19141                        break;
19142                    case LAYOUT_DIRECTION_LTR:
19143                    default:
19144                        mUserPaddingLeftInitial = padding.left;
19145                        mUserPaddingRightInitial = padding.right;
19146                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
19147                }
19148                mLeftPaddingDefined = false;
19149                mRightPaddingDefined = false;
19150            }
19151
19152            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
19153            // if it has a different minimum size, we should layout again
19154            if (mBackground == null
19155                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
19156                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
19157                requestLayout = true;
19158            }
19159
19160            // Set mBackground before we set this as the callback and start making other
19161            // background drawable state change calls. In particular, the setVisible call below
19162            // can result in drawables attempting to start animations or otherwise invalidate,
19163            // which requires the view set as the callback (us) to recognize the drawable as
19164            // belonging to it as per verifyDrawable.
19165            mBackground = background;
19166            if (background.isStateful()) {
19167                background.setState(getDrawableState());
19168            }
19169            if (isAttachedToWindow()) {
19170                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19171            }
19172
19173            applyBackgroundTint();
19174
19175            // Set callback last, since the view may still be initializing.
19176            background.setCallback(this);
19177
19178            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19179                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19180                requestLayout = true;
19181            }
19182        } else {
19183            /* Remove the background */
19184            mBackground = null;
19185            if ((mViewFlags & WILL_NOT_DRAW) != 0
19186                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
19187                mPrivateFlags |= PFLAG_SKIP_DRAW;
19188            }
19189
19190            /*
19191             * When the background is set, we try to apply its padding to this
19192             * View. When the background is removed, we don't touch this View's
19193             * padding. This is noted in the Javadocs. Hence, we don't need to
19194             * requestLayout(), the invalidate() below is sufficient.
19195             */
19196
19197            // The old background's minimum size could have affected this
19198            // View's layout, so let's requestLayout
19199            requestLayout = true;
19200        }
19201
19202        computeOpaqueFlags();
19203
19204        if (requestLayout) {
19205            requestLayout();
19206        }
19207
19208        mBackgroundSizeChanged = true;
19209        invalidate(true);
19210        invalidateOutline();
19211    }
19212
19213    /**
19214     * Gets the background drawable
19215     *
19216     * @return The drawable used as the background for this view, if any.
19217     *
19218     * @see #setBackground(Drawable)
19219     *
19220     * @attr ref android.R.styleable#View_background
19221     */
19222    public Drawable getBackground() {
19223        return mBackground;
19224    }
19225
19226    /**
19227     * Applies a tint to the background drawable. Does not modify the current tint
19228     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
19229     * <p>
19230     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
19231     * mutate the drawable and apply the specified tint and tint mode using
19232     * {@link Drawable#setTintList(ColorStateList)}.
19233     *
19234     * @param tint the tint to apply, may be {@code null} to clear tint
19235     *
19236     * @attr ref android.R.styleable#View_backgroundTint
19237     * @see #getBackgroundTintList()
19238     * @see Drawable#setTintList(ColorStateList)
19239     */
19240    public void setBackgroundTintList(@Nullable ColorStateList tint) {
19241        if (mBackgroundTint == null) {
19242            mBackgroundTint = new TintInfo();
19243        }
19244        mBackgroundTint.mTintList = tint;
19245        mBackgroundTint.mHasTintList = true;
19246
19247        applyBackgroundTint();
19248    }
19249
19250    /**
19251     * Return the tint applied to the background drawable, if specified.
19252     *
19253     * @return the tint applied to the background drawable
19254     * @attr ref android.R.styleable#View_backgroundTint
19255     * @see #setBackgroundTintList(ColorStateList)
19256     */
19257    @Nullable
19258    public ColorStateList getBackgroundTintList() {
19259        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
19260    }
19261
19262    /**
19263     * Specifies the blending mode used to apply the tint specified by
19264     * {@link #setBackgroundTintList(ColorStateList)}} to the background
19265     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
19266     *
19267     * @param tintMode the blending mode used to apply the tint, may be
19268     *                 {@code null} to clear tint
19269     * @attr ref android.R.styleable#View_backgroundTintMode
19270     * @see #getBackgroundTintMode()
19271     * @see Drawable#setTintMode(PorterDuff.Mode)
19272     */
19273    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
19274        if (mBackgroundTint == null) {
19275            mBackgroundTint = new TintInfo();
19276        }
19277        mBackgroundTint.mTintMode = tintMode;
19278        mBackgroundTint.mHasTintMode = true;
19279
19280        applyBackgroundTint();
19281    }
19282
19283    /**
19284     * Return the blending mode used to apply the tint to the background
19285     * drawable, if specified.
19286     *
19287     * @return the blending mode used to apply the tint to the background
19288     *         drawable
19289     * @attr ref android.R.styleable#View_backgroundTintMode
19290     * @see #setBackgroundTintMode(PorterDuff.Mode)
19291     */
19292    @Nullable
19293    public PorterDuff.Mode getBackgroundTintMode() {
19294        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
19295    }
19296
19297    private void applyBackgroundTint() {
19298        if (mBackground != null && mBackgroundTint != null) {
19299            final TintInfo tintInfo = mBackgroundTint;
19300            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
19301                mBackground = mBackground.mutate();
19302
19303                if (tintInfo.mHasTintList) {
19304                    mBackground.setTintList(tintInfo.mTintList);
19305                }
19306
19307                if (tintInfo.mHasTintMode) {
19308                    mBackground.setTintMode(tintInfo.mTintMode);
19309                }
19310
19311                // The drawable (or one of its children) may not have been
19312                // stateful before applying the tint, so let's try again.
19313                if (mBackground.isStateful()) {
19314                    mBackground.setState(getDrawableState());
19315                }
19316            }
19317        }
19318    }
19319
19320    /**
19321     * Returns the drawable used as the foreground of this View. The
19322     * foreground drawable, if non-null, is always drawn on top of the view's content.
19323     *
19324     * @return a Drawable or null if no foreground was set
19325     *
19326     * @see #onDrawForeground(Canvas)
19327     */
19328    public Drawable getForeground() {
19329        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19330    }
19331
19332    /**
19333     * Supply a Drawable that is to be rendered on top of all of the content in the view.
19334     *
19335     * @param foreground the Drawable to be drawn on top of the children
19336     *
19337     * @attr ref android.R.styleable#View_foreground
19338     */
19339    public void setForeground(Drawable foreground) {
19340        if (mForegroundInfo == null) {
19341            if (foreground == null) {
19342                // Nothing to do.
19343                return;
19344            }
19345            mForegroundInfo = new ForegroundInfo();
19346        }
19347
19348        if (foreground == mForegroundInfo.mDrawable) {
19349            // Nothing to do
19350            return;
19351        }
19352
19353        if (mForegroundInfo.mDrawable != null) {
19354            if (isAttachedToWindow()) {
19355                mForegroundInfo.mDrawable.setVisible(false, false);
19356            }
19357            mForegroundInfo.mDrawable.setCallback(null);
19358            unscheduleDrawable(mForegroundInfo.mDrawable);
19359        }
19360
19361        mForegroundInfo.mDrawable = foreground;
19362        mForegroundInfo.mBoundsChanged = true;
19363        if (foreground != null) {
19364            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19365                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19366            }
19367            foreground.setLayoutDirection(getLayoutDirection());
19368            if (foreground.isStateful()) {
19369                foreground.setState(getDrawableState());
19370            }
19371            applyForegroundTint();
19372            if (isAttachedToWindow()) {
19373                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19374            }
19375            // Set callback last, since the view may still be initializing.
19376            foreground.setCallback(this);
19377        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
19378            mPrivateFlags |= PFLAG_SKIP_DRAW;
19379        }
19380        requestLayout();
19381        invalidate();
19382    }
19383
19384    /**
19385     * Magic bit used to support features of framework-internal window decor implementation details.
19386     * This used to live exclusively in FrameLayout.
19387     *
19388     * @return true if the foreground should draw inside the padding region or false
19389     *         if it should draw inset by the view's padding
19390     * @hide internal use only; only used by FrameLayout and internal screen layouts.
19391     */
19392    public boolean isForegroundInsidePadding() {
19393        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
19394    }
19395
19396    /**
19397     * Describes how the foreground is positioned.
19398     *
19399     * @return foreground gravity.
19400     *
19401     * @see #setForegroundGravity(int)
19402     *
19403     * @attr ref android.R.styleable#View_foregroundGravity
19404     */
19405    public int getForegroundGravity() {
19406        return mForegroundInfo != null ? mForegroundInfo.mGravity
19407                : Gravity.START | Gravity.TOP;
19408    }
19409
19410    /**
19411     * Describes how the foreground is positioned. Defaults to START and TOP.
19412     *
19413     * @param gravity see {@link android.view.Gravity}
19414     *
19415     * @see #getForegroundGravity()
19416     *
19417     * @attr ref android.R.styleable#View_foregroundGravity
19418     */
19419    public void setForegroundGravity(int gravity) {
19420        if (mForegroundInfo == null) {
19421            mForegroundInfo = new ForegroundInfo();
19422        }
19423
19424        if (mForegroundInfo.mGravity != gravity) {
19425            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
19426                gravity |= Gravity.START;
19427            }
19428
19429            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
19430                gravity |= Gravity.TOP;
19431            }
19432
19433            mForegroundInfo.mGravity = gravity;
19434            requestLayout();
19435        }
19436    }
19437
19438    /**
19439     * Applies a tint to the foreground drawable. Does not modify the current tint
19440     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
19441     * <p>
19442     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
19443     * mutate the drawable and apply the specified tint and tint mode using
19444     * {@link Drawable#setTintList(ColorStateList)}.
19445     *
19446     * @param tint the tint to apply, may be {@code null} to clear tint
19447     *
19448     * @attr ref android.R.styleable#View_foregroundTint
19449     * @see #getForegroundTintList()
19450     * @see Drawable#setTintList(ColorStateList)
19451     */
19452    public void setForegroundTintList(@Nullable ColorStateList tint) {
19453        if (mForegroundInfo == null) {
19454            mForegroundInfo = new ForegroundInfo();
19455        }
19456        if (mForegroundInfo.mTintInfo == null) {
19457            mForegroundInfo.mTintInfo = new TintInfo();
19458        }
19459        mForegroundInfo.mTintInfo.mTintList = tint;
19460        mForegroundInfo.mTintInfo.mHasTintList = true;
19461
19462        applyForegroundTint();
19463    }
19464
19465    /**
19466     * Return the tint applied to the foreground drawable, if specified.
19467     *
19468     * @return the tint applied to the foreground drawable
19469     * @attr ref android.R.styleable#View_foregroundTint
19470     * @see #setForegroundTintList(ColorStateList)
19471     */
19472    @Nullable
19473    public ColorStateList getForegroundTintList() {
19474        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
19475                ? mForegroundInfo.mTintInfo.mTintList : null;
19476    }
19477
19478    /**
19479     * Specifies the blending mode used to apply the tint specified by
19480     * {@link #setForegroundTintList(ColorStateList)}} to the background
19481     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
19482     *
19483     * @param tintMode the blending mode used to apply the tint, may be
19484     *                 {@code null} to clear tint
19485     * @attr ref android.R.styleable#View_foregroundTintMode
19486     * @see #getForegroundTintMode()
19487     * @see Drawable#setTintMode(PorterDuff.Mode)
19488     */
19489    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
19490        if (mForegroundInfo == null) {
19491            mForegroundInfo = new ForegroundInfo();
19492        }
19493        if (mForegroundInfo.mTintInfo == null) {
19494            mForegroundInfo.mTintInfo = new TintInfo();
19495        }
19496        mForegroundInfo.mTintInfo.mTintMode = tintMode;
19497        mForegroundInfo.mTintInfo.mHasTintMode = true;
19498
19499        applyForegroundTint();
19500    }
19501
19502    /**
19503     * Return the blending mode used to apply the tint to the foreground
19504     * drawable, if specified.
19505     *
19506     * @return the blending mode used to apply the tint to the foreground
19507     *         drawable
19508     * @attr ref android.R.styleable#View_foregroundTintMode
19509     * @see #setForegroundTintMode(PorterDuff.Mode)
19510     */
19511    @Nullable
19512    public PorterDuff.Mode getForegroundTintMode() {
19513        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
19514                ? mForegroundInfo.mTintInfo.mTintMode : null;
19515    }
19516
19517    private void applyForegroundTint() {
19518        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19519                && mForegroundInfo.mTintInfo != null) {
19520            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
19521            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
19522                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
19523
19524                if (tintInfo.mHasTintList) {
19525                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
19526                }
19527
19528                if (tintInfo.mHasTintMode) {
19529                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
19530                }
19531
19532                // The drawable (or one of its children) may not have been
19533                // stateful before applying the tint, so let's try again.
19534                if (mForegroundInfo.mDrawable.isStateful()) {
19535                    mForegroundInfo.mDrawable.setState(getDrawableState());
19536                }
19537            }
19538        }
19539    }
19540
19541    /**
19542     * Draw any foreground content for this view.
19543     *
19544     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
19545     * drawable or other view-specific decorations. The foreground is drawn on top of the
19546     * primary view content.</p>
19547     *
19548     * @param canvas canvas to draw into
19549     */
19550    public void onDrawForeground(Canvas canvas) {
19551        onDrawScrollIndicators(canvas);
19552        onDrawScrollBars(canvas);
19553
19554        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19555        if (foreground != null) {
19556            if (mForegroundInfo.mBoundsChanged) {
19557                mForegroundInfo.mBoundsChanged = false;
19558                final Rect selfBounds = mForegroundInfo.mSelfBounds;
19559                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
19560
19561                if (mForegroundInfo.mInsidePadding) {
19562                    selfBounds.set(0, 0, getWidth(), getHeight());
19563                } else {
19564                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
19565                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
19566                }
19567
19568                final int ld = getLayoutDirection();
19569                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
19570                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
19571                foreground.setBounds(overlayBounds);
19572            }
19573
19574            foreground.draw(canvas);
19575        }
19576    }
19577
19578    /**
19579     * Sets the padding. The view may add on the space required to display
19580     * the scrollbars, depending on the style and visibility of the scrollbars.
19581     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
19582     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
19583     * from the values set in this call.
19584     *
19585     * @attr ref android.R.styleable#View_padding
19586     * @attr ref android.R.styleable#View_paddingBottom
19587     * @attr ref android.R.styleable#View_paddingLeft
19588     * @attr ref android.R.styleable#View_paddingRight
19589     * @attr ref android.R.styleable#View_paddingTop
19590     * @param left the left padding in pixels
19591     * @param top the top padding in pixels
19592     * @param right the right padding in pixels
19593     * @param bottom the bottom padding in pixels
19594     */
19595    public void setPadding(int left, int top, int right, int bottom) {
19596        resetResolvedPaddingInternal();
19597
19598        mUserPaddingStart = UNDEFINED_PADDING;
19599        mUserPaddingEnd = UNDEFINED_PADDING;
19600
19601        mUserPaddingLeftInitial = left;
19602        mUserPaddingRightInitial = right;
19603
19604        mLeftPaddingDefined = true;
19605        mRightPaddingDefined = true;
19606
19607        internalSetPadding(left, top, right, bottom);
19608    }
19609
19610    /**
19611     * @hide
19612     */
19613    protected void internalSetPadding(int left, int top, int right, int bottom) {
19614        mUserPaddingLeft = left;
19615        mUserPaddingRight = right;
19616        mUserPaddingBottom = bottom;
19617
19618        final int viewFlags = mViewFlags;
19619        boolean changed = false;
19620
19621        // Common case is there are no scroll bars.
19622        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
19623            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
19624                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
19625                        ? 0 : getVerticalScrollbarWidth();
19626                switch (mVerticalScrollbarPosition) {
19627                    case SCROLLBAR_POSITION_DEFAULT:
19628                        if (isLayoutRtl()) {
19629                            left += offset;
19630                        } else {
19631                            right += offset;
19632                        }
19633                        break;
19634                    case SCROLLBAR_POSITION_RIGHT:
19635                        right += offset;
19636                        break;
19637                    case SCROLLBAR_POSITION_LEFT:
19638                        left += offset;
19639                        break;
19640                }
19641            }
19642            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
19643                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
19644                        ? 0 : getHorizontalScrollbarHeight();
19645            }
19646        }
19647
19648        if (mPaddingLeft != left) {
19649            changed = true;
19650            mPaddingLeft = left;
19651        }
19652        if (mPaddingTop != top) {
19653            changed = true;
19654            mPaddingTop = top;
19655        }
19656        if (mPaddingRight != right) {
19657            changed = true;
19658            mPaddingRight = right;
19659        }
19660        if (mPaddingBottom != bottom) {
19661            changed = true;
19662            mPaddingBottom = bottom;
19663        }
19664
19665        if (changed) {
19666            requestLayout();
19667            invalidateOutline();
19668        }
19669    }
19670
19671    /**
19672     * Sets the relative padding. The view may add on the space required to display
19673     * the scrollbars, depending on the style and visibility of the scrollbars.
19674     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
19675     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
19676     * from the values set in this call.
19677     *
19678     * @attr ref android.R.styleable#View_padding
19679     * @attr ref android.R.styleable#View_paddingBottom
19680     * @attr ref android.R.styleable#View_paddingStart
19681     * @attr ref android.R.styleable#View_paddingEnd
19682     * @attr ref android.R.styleable#View_paddingTop
19683     * @param start the start padding in pixels
19684     * @param top the top padding in pixels
19685     * @param end the end padding in pixels
19686     * @param bottom the bottom padding in pixels
19687     */
19688    public void setPaddingRelative(int start, int top, int end, int bottom) {
19689        resetResolvedPaddingInternal();
19690
19691        mUserPaddingStart = start;
19692        mUserPaddingEnd = end;
19693        mLeftPaddingDefined = true;
19694        mRightPaddingDefined = true;
19695
19696        switch(getLayoutDirection()) {
19697            case LAYOUT_DIRECTION_RTL:
19698                mUserPaddingLeftInitial = end;
19699                mUserPaddingRightInitial = start;
19700                internalSetPadding(end, top, start, bottom);
19701                break;
19702            case LAYOUT_DIRECTION_LTR:
19703            default:
19704                mUserPaddingLeftInitial = start;
19705                mUserPaddingRightInitial = end;
19706                internalSetPadding(start, top, end, bottom);
19707        }
19708    }
19709
19710    /**
19711     * Returns the top padding of this view.
19712     *
19713     * @return the top padding in pixels
19714     */
19715    public int getPaddingTop() {
19716        return mPaddingTop;
19717    }
19718
19719    /**
19720     * Returns the bottom padding of this view. If there are inset and enabled
19721     * scrollbars, this value may include the space required to display the
19722     * scrollbars as well.
19723     *
19724     * @return the bottom padding in pixels
19725     */
19726    public int getPaddingBottom() {
19727        return mPaddingBottom;
19728    }
19729
19730    /**
19731     * Returns the left padding of this view. If there are inset and enabled
19732     * scrollbars, this value may include the space required to display the
19733     * scrollbars as well.
19734     *
19735     * @return the left padding in pixels
19736     */
19737    public int getPaddingLeft() {
19738        if (!isPaddingResolved()) {
19739            resolvePadding();
19740        }
19741        return mPaddingLeft;
19742    }
19743
19744    /**
19745     * Returns the start padding of this view depending on its resolved layout direction.
19746     * If there are inset and enabled scrollbars, this value may include the space
19747     * required to display the scrollbars as well.
19748     *
19749     * @return the start padding in pixels
19750     */
19751    public int getPaddingStart() {
19752        if (!isPaddingResolved()) {
19753            resolvePadding();
19754        }
19755        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
19756                mPaddingRight : mPaddingLeft;
19757    }
19758
19759    /**
19760     * Returns the right padding of this view. If there are inset and enabled
19761     * scrollbars, this value may include the space required to display the
19762     * scrollbars as well.
19763     *
19764     * @return the right padding in pixels
19765     */
19766    public int getPaddingRight() {
19767        if (!isPaddingResolved()) {
19768            resolvePadding();
19769        }
19770        return mPaddingRight;
19771    }
19772
19773    /**
19774     * Returns the end padding of this view depending on its resolved layout direction.
19775     * If there are inset and enabled scrollbars, this value may include the space
19776     * required to display the scrollbars as well.
19777     *
19778     * @return the end padding in pixels
19779     */
19780    public int getPaddingEnd() {
19781        if (!isPaddingResolved()) {
19782            resolvePadding();
19783        }
19784        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
19785                mPaddingLeft : mPaddingRight;
19786    }
19787
19788    /**
19789     * Return if the padding has been set through relative values
19790     * {@link #setPaddingRelative(int, int, int, int)} or through
19791     * @attr ref android.R.styleable#View_paddingStart or
19792     * @attr ref android.R.styleable#View_paddingEnd
19793     *
19794     * @return true if the padding is relative or false if it is not.
19795     */
19796    public boolean isPaddingRelative() {
19797        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
19798    }
19799
19800    Insets computeOpticalInsets() {
19801        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
19802    }
19803
19804    /**
19805     * @hide
19806     */
19807    public void resetPaddingToInitialValues() {
19808        if (isRtlCompatibilityMode()) {
19809            mPaddingLeft = mUserPaddingLeftInitial;
19810            mPaddingRight = mUserPaddingRightInitial;
19811            return;
19812        }
19813        if (isLayoutRtl()) {
19814            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
19815            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
19816        } else {
19817            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
19818            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
19819        }
19820    }
19821
19822    /**
19823     * @hide
19824     */
19825    public Insets getOpticalInsets() {
19826        if (mLayoutInsets == null) {
19827            mLayoutInsets = computeOpticalInsets();
19828        }
19829        return mLayoutInsets;
19830    }
19831
19832    /**
19833     * Set this view's optical insets.
19834     *
19835     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
19836     * property. Views that compute their own optical insets should call it as part of measurement.
19837     * This method does not request layout. If you are setting optical insets outside of
19838     * measure/layout itself you will want to call requestLayout() yourself.
19839     * </p>
19840     * @hide
19841     */
19842    public void setOpticalInsets(Insets insets) {
19843        mLayoutInsets = insets;
19844    }
19845
19846    /**
19847     * Changes the selection state of this view. A view can be selected or not.
19848     * Note that selection is not the same as focus. Views are typically
19849     * selected in the context of an AdapterView like ListView or GridView;
19850     * the selected view is the view that is highlighted.
19851     *
19852     * @param selected true if the view must be selected, false otherwise
19853     */
19854    public void setSelected(boolean selected) {
19855        //noinspection DoubleNegation
19856        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
19857            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
19858            if (!selected) resetPressedState();
19859            invalidate(true);
19860            refreshDrawableState();
19861            dispatchSetSelected(selected);
19862            if (selected) {
19863                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
19864            } else {
19865                notifyViewAccessibilityStateChangedIfNeeded(
19866                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
19867            }
19868        }
19869    }
19870
19871    /**
19872     * Dispatch setSelected to all of this View's children.
19873     *
19874     * @see #setSelected(boolean)
19875     *
19876     * @param selected The new selected state
19877     */
19878    protected void dispatchSetSelected(boolean selected) {
19879    }
19880
19881    /**
19882     * Indicates the selection state of this view.
19883     *
19884     * @return true if the view is selected, false otherwise
19885     */
19886    @ViewDebug.ExportedProperty
19887    public boolean isSelected() {
19888        return (mPrivateFlags & PFLAG_SELECTED) != 0;
19889    }
19890
19891    /**
19892     * Changes the activated state of this view. A view can be activated or not.
19893     * Note that activation is not the same as selection.  Selection is
19894     * a transient property, representing the view (hierarchy) the user is
19895     * currently interacting with.  Activation is a longer-term state that the
19896     * user can move views in and out of.  For example, in a list view with
19897     * single or multiple selection enabled, the views in the current selection
19898     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
19899     * here.)  The activated state is propagated down to children of the view it
19900     * is set on.
19901     *
19902     * @param activated true if the view must be activated, false otherwise
19903     */
19904    public void setActivated(boolean activated) {
19905        //noinspection DoubleNegation
19906        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
19907            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
19908            invalidate(true);
19909            refreshDrawableState();
19910            dispatchSetActivated(activated);
19911        }
19912    }
19913
19914    /**
19915     * Dispatch setActivated to all of this View's children.
19916     *
19917     * @see #setActivated(boolean)
19918     *
19919     * @param activated The new activated state
19920     */
19921    protected void dispatchSetActivated(boolean activated) {
19922    }
19923
19924    /**
19925     * Indicates the activation state of this view.
19926     *
19927     * @return true if the view is activated, false otherwise
19928     */
19929    @ViewDebug.ExportedProperty
19930    public boolean isActivated() {
19931        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
19932    }
19933
19934    /**
19935     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
19936     * observer can be used to get notifications when global events, like
19937     * layout, happen.
19938     *
19939     * The returned ViewTreeObserver observer is not guaranteed to remain
19940     * valid for the lifetime of this View. If the caller of this method keeps
19941     * a long-lived reference to ViewTreeObserver, it should always check for
19942     * the return value of {@link ViewTreeObserver#isAlive()}.
19943     *
19944     * @return The ViewTreeObserver for this view's hierarchy.
19945     */
19946    public ViewTreeObserver getViewTreeObserver() {
19947        if (mAttachInfo != null) {
19948            return mAttachInfo.mTreeObserver;
19949        }
19950        if (mFloatingTreeObserver == null) {
19951            mFloatingTreeObserver = new ViewTreeObserver(mContext);
19952        }
19953        return mFloatingTreeObserver;
19954    }
19955
19956    /**
19957     * <p>Finds the topmost view in the current view hierarchy.</p>
19958     *
19959     * @return the topmost view containing this view
19960     */
19961    public View getRootView() {
19962        if (mAttachInfo != null) {
19963            final View v = mAttachInfo.mRootView;
19964            if (v != null) {
19965                return v;
19966            }
19967        }
19968
19969        View parent = this;
19970
19971        while (parent.mParent != null && parent.mParent instanceof View) {
19972            parent = (View) parent.mParent;
19973        }
19974
19975        return parent;
19976    }
19977
19978    /**
19979     * Transforms a motion event from view-local coordinates to on-screen
19980     * coordinates.
19981     *
19982     * @param ev the view-local motion event
19983     * @return false if the transformation could not be applied
19984     * @hide
19985     */
19986    public boolean toGlobalMotionEvent(MotionEvent ev) {
19987        final AttachInfo info = mAttachInfo;
19988        if (info == null) {
19989            return false;
19990        }
19991
19992        final Matrix m = info.mTmpMatrix;
19993        m.set(Matrix.IDENTITY_MATRIX);
19994        transformMatrixToGlobal(m);
19995        ev.transform(m);
19996        return true;
19997    }
19998
19999    /**
20000     * Transforms a motion event from on-screen coordinates to view-local
20001     * coordinates.
20002     *
20003     * @param ev the on-screen motion event
20004     * @return false if the transformation could not be applied
20005     * @hide
20006     */
20007    public boolean toLocalMotionEvent(MotionEvent ev) {
20008        final AttachInfo info = mAttachInfo;
20009        if (info == null) {
20010            return false;
20011        }
20012
20013        final Matrix m = info.mTmpMatrix;
20014        m.set(Matrix.IDENTITY_MATRIX);
20015        transformMatrixToLocal(m);
20016        ev.transform(m);
20017        return true;
20018    }
20019
20020    /**
20021     * Modifies the input matrix such that it maps view-local coordinates to
20022     * on-screen coordinates.
20023     *
20024     * @param m input matrix to modify
20025     * @hide
20026     */
20027    public void transformMatrixToGlobal(Matrix m) {
20028        final ViewParent parent = mParent;
20029        if (parent instanceof View) {
20030            final View vp = (View) parent;
20031            vp.transformMatrixToGlobal(m);
20032            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
20033        } else if (parent instanceof ViewRootImpl) {
20034            final ViewRootImpl vr = (ViewRootImpl) parent;
20035            vr.transformMatrixToGlobal(m);
20036            m.preTranslate(0, -vr.mCurScrollY);
20037        }
20038
20039        m.preTranslate(mLeft, mTop);
20040
20041        if (!hasIdentityMatrix()) {
20042            m.preConcat(getMatrix());
20043        }
20044    }
20045
20046    /**
20047     * Modifies the input matrix such that it maps on-screen coordinates to
20048     * view-local coordinates.
20049     *
20050     * @param m input matrix to modify
20051     * @hide
20052     */
20053    public void transformMatrixToLocal(Matrix m) {
20054        final ViewParent parent = mParent;
20055        if (parent instanceof View) {
20056            final View vp = (View) parent;
20057            vp.transformMatrixToLocal(m);
20058            m.postTranslate(vp.mScrollX, vp.mScrollY);
20059        } else if (parent instanceof ViewRootImpl) {
20060            final ViewRootImpl vr = (ViewRootImpl) parent;
20061            vr.transformMatrixToLocal(m);
20062            m.postTranslate(0, vr.mCurScrollY);
20063        }
20064
20065        m.postTranslate(-mLeft, -mTop);
20066
20067        if (!hasIdentityMatrix()) {
20068            m.postConcat(getInverseMatrix());
20069        }
20070    }
20071
20072    /**
20073     * @hide
20074     */
20075    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
20076            @ViewDebug.IntToString(from = 0, to = "x"),
20077            @ViewDebug.IntToString(from = 1, to = "y")
20078    })
20079    public int[] getLocationOnScreen() {
20080        int[] location = new int[2];
20081        getLocationOnScreen(location);
20082        return location;
20083    }
20084
20085    /**
20086     * <p>Computes the coordinates of this view on the screen. The argument
20087     * must be an array of two integers. After the method returns, the array
20088     * contains the x and y location in that order.</p>
20089     *
20090     * @param outLocation an array of two integers in which to hold the coordinates
20091     */
20092    public void getLocationOnScreen(@Size(2) int[] outLocation) {
20093        getLocationInWindow(outLocation);
20094
20095        final AttachInfo info = mAttachInfo;
20096        if (info != null) {
20097            outLocation[0] += info.mWindowLeft;
20098            outLocation[1] += info.mWindowTop;
20099        }
20100    }
20101
20102    /**
20103     * <p>Computes the coordinates of this view in its window. The argument
20104     * must be an array of two integers. After the method returns, the array
20105     * contains the x and y location in that order.</p>
20106     *
20107     * @param outLocation an array of two integers in which to hold the coordinates
20108     */
20109    public void getLocationInWindow(@Size(2) int[] outLocation) {
20110        if (outLocation == null || outLocation.length < 2) {
20111            throw new IllegalArgumentException("outLocation must be an array of two integers");
20112        }
20113
20114        outLocation[0] = 0;
20115        outLocation[1] = 0;
20116
20117        transformFromViewToWindowSpace(outLocation);
20118    }
20119
20120    /** @hide */
20121    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
20122        if (inOutLocation == null || inOutLocation.length < 2) {
20123            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
20124        }
20125
20126        if (mAttachInfo == null) {
20127            // When the view is not attached to a window, this method does not make sense
20128            inOutLocation[0] = inOutLocation[1] = 0;
20129            return;
20130        }
20131
20132        float position[] = mAttachInfo.mTmpTransformLocation;
20133        position[0] = inOutLocation[0];
20134        position[1] = inOutLocation[1];
20135
20136        if (!hasIdentityMatrix()) {
20137            getMatrix().mapPoints(position);
20138        }
20139
20140        position[0] += mLeft;
20141        position[1] += mTop;
20142
20143        ViewParent viewParent = mParent;
20144        while (viewParent instanceof View) {
20145            final View view = (View) viewParent;
20146
20147            position[0] -= view.mScrollX;
20148            position[1] -= view.mScrollY;
20149
20150            if (!view.hasIdentityMatrix()) {
20151                view.getMatrix().mapPoints(position);
20152            }
20153
20154            position[0] += view.mLeft;
20155            position[1] += view.mTop;
20156
20157            viewParent = view.mParent;
20158         }
20159
20160        if (viewParent instanceof ViewRootImpl) {
20161            // *cough*
20162            final ViewRootImpl vr = (ViewRootImpl) viewParent;
20163            position[1] -= vr.mCurScrollY;
20164        }
20165
20166        inOutLocation[0] = Math.round(position[0]);
20167        inOutLocation[1] = Math.round(position[1]);
20168    }
20169
20170    /**
20171     * @param id the id of the view to be found
20172     * @return the view of the specified id, null if cannot be found
20173     * @hide
20174     */
20175    protected View findViewTraversal(@IdRes int id) {
20176        if (id == mID) {
20177            return this;
20178        }
20179        return null;
20180    }
20181
20182    /**
20183     * @param tag the tag of the view to be found
20184     * @return the view of specified tag, null if cannot be found
20185     * @hide
20186     */
20187    protected View findViewWithTagTraversal(Object tag) {
20188        if (tag != null && tag.equals(mTag)) {
20189            return this;
20190        }
20191        return null;
20192    }
20193
20194    /**
20195     * @param predicate The predicate to evaluate.
20196     * @param childToSkip If not null, ignores this child during the recursive traversal.
20197     * @return The first view that matches the predicate or null.
20198     * @hide
20199     */
20200    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
20201        if (predicate.test(this)) {
20202            return this;
20203        }
20204        return null;
20205    }
20206
20207    /**
20208     * Look for a child view with the given id.  If this view has the given
20209     * id, return this view.
20210     *
20211     * @param id The id to search for.
20212     * @return The view that has the given id in the hierarchy or null
20213     */
20214    @Nullable
20215    public final View findViewById(@IdRes int id) {
20216        if (id < 0) {
20217            return null;
20218        }
20219        return findViewTraversal(id);
20220    }
20221
20222    /**
20223     * Finds a view by its unuque and stable accessibility id.
20224     *
20225     * @param accessibilityId The searched accessibility id.
20226     * @return The found view.
20227     */
20228    final View findViewByAccessibilityId(int accessibilityId) {
20229        if (accessibilityId < 0) {
20230            return null;
20231        }
20232        View view = findViewByAccessibilityIdTraversal(accessibilityId);
20233        if (view != null) {
20234            return view.includeForAccessibility() ? view : null;
20235        }
20236        return null;
20237    }
20238
20239    /**
20240     * Performs the traversal to find a view by its unuque and stable accessibility id.
20241     *
20242     * <strong>Note:</strong>This method does not stop at the root namespace
20243     * boundary since the user can touch the screen at an arbitrary location
20244     * potentially crossing the root namespace bounday which will send an
20245     * accessibility event to accessibility services and they should be able
20246     * to obtain the event source. Also accessibility ids are guaranteed to be
20247     * unique in the window.
20248     *
20249     * @param accessibilityId The accessibility id.
20250     * @return The found view.
20251     *
20252     * @hide
20253     */
20254    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
20255        if (getAccessibilityViewId() == accessibilityId) {
20256            return this;
20257        }
20258        return null;
20259    }
20260
20261    /**
20262     * Look for a child view with the given tag.  If this view has the given
20263     * tag, return this view.
20264     *
20265     * @param tag The tag to search for, using "tag.equals(getTag())".
20266     * @return The View that has the given tag in the hierarchy or null
20267     */
20268    public final View findViewWithTag(Object tag) {
20269        if (tag == null) {
20270            return null;
20271        }
20272        return findViewWithTagTraversal(tag);
20273    }
20274
20275    /**
20276     * Look for a child view that matches the specified predicate.
20277     * If this view matches the predicate, return this view.
20278     *
20279     * @param predicate The predicate to evaluate.
20280     * @return The first view that matches the predicate or null.
20281     * @hide
20282     */
20283    public final View findViewByPredicate(Predicate<View> predicate) {
20284        return findViewByPredicateTraversal(predicate, null);
20285    }
20286
20287    /**
20288     * Look for a child view that matches the specified predicate,
20289     * starting with the specified view and its descendents and then
20290     * recusively searching the ancestors and siblings of that view
20291     * until this view is reached.
20292     *
20293     * This method is useful in cases where the predicate does not match
20294     * a single unique view (perhaps multiple views use the same id)
20295     * and we are trying to find the view that is "closest" in scope to the
20296     * starting view.
20297     *
20298     * @param start The view to start from.
20299     * @param predicate The predicate to evaluate.
20300     * @return The first view that matches the predicate or null.
20301     * @hide
20302     */
20303    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
20304        View childToSkip = null;
20305        for (;;) {
20306            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
20307            if (view != null || start == this) {
20308                return view;
20309            }
20310
20311            ViewParent parent = start.getParent();
20312            if (parent == null || !(parent instanceof View)) {
20313                return null;
20314            }
20315
20316            childToSkip = start;
20317            start = (View) parent;
20318        }
20319    }
20320
20321    /**
20322     * Sets the identifier for this view. The identifier does not have to be
20323     * unique in this view's hierarchy. The identifier should be a positive
20324     * number.
20325     *
20326     * @see #NO_ID
20327     * @see #getId()
20328     * @see #findViewById(int)
20329     *
20330     * @param id a number used to identify the view
20331     *
20332     * @attr ref android.R.styleable#View_id
20333     */
20334    public void setId(@IdRes int id) {
20335        mID = id;
20336        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
20337            mID = generateViewId();
20338        }
20339    }
20340
20341    /**
20342     * {@hide}
20343     *
20344     * @param isRoot true if the view belongs to the root namespace, false
20345     *        otherwise
20346     */
20347    public void setIsRootNamespace(boolean isRoot) {
20348        if (isRoot) {
20349            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
20350        } else {
20351            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
20352        }
20353    }
20354
20355    /**
20356     * {@hide}
20357     *
20358     * @return true if the view belongs to the root namespace, false otherwise
20359     */
20360    public boolean isRootNamespace() {
20361        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
20362    }
20363
20364    /**
20365     * Returns this view's identifier.
20366     *
20367     * @return a positive integer used to identify the view or {@link #NO_ID}
20368     *         if the view has no ID
20369     *
20370     * @see #setId(int)
20371     * @see #findViewById(int)
20372     * @attr ref android.R.styleable#View_id
20373     */
20374    @IdRes
20375    @ViewDebug.CapturedViewProperty
20376    public int getId() {
20377        return mID;
20378    }
20379
20380    /**
20381     * Returns this view's tag.
20382     *
20383     * @return the Object stored in this view as a tag, or {@code null} if not
20384     *         set
20385     *
20386     * @see #setTag(Object)
20387     * @see #getTag(int)
20388     */
20389    @ViewDebug.ExportedProperty
20390    public Object getTag() {
20391        return mTag;
20392    }
20393
20394    /**
20395     * Sets the tag associated with this view. A tag can be used to mark
20396     * a view in its hierarchy and does not have to be unique within the
20397     * hierarchy. Tags can also be used to store data within a view without
20398     * resorting to another data structure.
20399     *
20400     * @param tag an Object to tag the view with
20401     *
20402     * @see #getTag()
20403     * @see #setTag(int, Object)
20404     */
20405    public void setTag(final Object tag) {
20406        mTag = tag;
20407    }
20408
20409    /**
20410     * Returns the tag associated with this view and the specified key.
20411     *
20412     * @param key The key identifying the tag
20413     *
20414     * @return the Object stored in this view as a tag, or {@code null} if not
20415     *         set
20416     *
20417     * @see #setTag(int, Object)
20418     * @see #getTag()
20419     */
20420    public Object getTag(int key) {
20421        if (mKeyedTags != null) return mKeyedTags.get(key);
20422        return null;
20423    }
20424
20425    /**
20426     * Sets a tag associated with this view and a key. A tag can be used
20427     * to mark a view in its hierarchy and does not have to be unique within
20428     * the hierarchy. Tags can also be used to store data within a view
20429     * without resorting to another data structure.
20430     *
20431     * The specified key should be an id declared in the resources of the
20432     * application to ensure it is unique (see the <a
20433     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
20434     * Keys identified as belonging to
20435     * the Android framework or not associated with any package will cause
20436     * an {@link IllegalArgumentException} to be thrown.
20437     *
20438     * @param key The key identifying the tag
20439     * @param tag An Object to tag the view with
20440     *
20441     * @throws IllegalArgumentException If they specified key is not valid
20442     *
20443     * @see #setTag(Object)
20444     * @see #getTag(int)
20445     */
20446    public void setTag(int key, final Object tag) {
20447        // If the package id is 0x00 or 0x01, it's either an undefined package
20448        // or a framework id
20449        if ((key >>> 24) < 2) {
20450            throw new IllegalArgumentException("The key must be an application-specific "
20451                    + "resource id.");
20452        }
20453
20454        setKeyedTag(key, tag);
20455    }
20456
20457    /**
20458     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
20459     * framework id.
20460     *
20461     * @hide
20462     */
20463    public void setTagInternal(int key, Object tag) {
20464        if ((key >>> 24) != 0x1) {
20465            throw new IllegalArgumentException("The key must be a framework-specific "
20466                    + "resource id.");
20467        }
20468
20469        setKeyedTag(key, tag);
20470    }
20471
20472    private void setKeyedTag(int key, Object tag) {
20473        if (mKeyedTags == null) {
20474            mKeyedTags = new SparseArray<Object>(2);
20475        }
20476
20477        mKeyedTags.put(key, tag);
20478    }
20479
20480    /**
20481     * Prints information about this view in the log output, with the tag
20482     * {@link #VIEW_LOG_TAG}.
20483     *
20484     * @hide
20485     */
20486    public void debug() {
20487        debug(0);
20488    }
20489
20490    /**
20491     * Prints information about this view in the log output, with the tag
20492     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
20493     * indentation defined by the <code>depth</code>.
20494     *
20495     * @param depth the indentation level
20496     *
20497     * @hide
20498     */
20499    protected void debug(int depth) {
20500        String output = debugIndent(depth - 1);
20501
20502        output += "+ " + this;
20503        int id = getId();
20504        if (id != -1) {
20505            output += " (id=" + id + ")";
20506        }
20507        Object tag = getTag();
20508        if (tag != null) {
20509            output += " (tag=" + tag + ")";
20510        }
20511        Log.d(VIEW_LOG_TAG, output);
20512
20513        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
20514            output = debugIndent(depth) + " FOCUSED";
20515            Log.d(VIEW_LOG_TAG, output);
20516        }
20517
20518        output = debugIndent(depth);
20519        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
20520                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
20521                + "} ";
20522        Log.d(VIEW_LOG_TAG, output);
20523
20524        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
20525                || mPaddingBottom != 0) {
20526            output = debugIndent(depth);
20527            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
20528                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
20529            Log.d(VIEW_LOG_TAG, output);
20530        }
20531
20532        output = debugIndent(depth);
20533        output += "mMeasureWidth=" + mMeasuredWidth +
20534                " mMeasureHeight=" + mMeasuredHeight;
20535        Log.d(VIEW_LOG_TAG, output);
20536
20537        output = debugIndent(depth);
20538        if (mLayoutParams == null) {
20539            output += "BAD! no layout params";
20540        } else {
20541            output = mLayoutParams.debug(output);
20542        }
20543        Log.d(VIEW_LOG_TAG, output);
20544
20545        output = debugIndent(depth);
20546        output += "flags={";
20547        output += View.printFlags(mViewFlags);
20548        output += "}";
20549        Log.d(VIEW_LOG_TAG, output);
20550
20551        output = debugIndent(depth);
20552        output += "privateFlags={";
20553        output += View.printPrivateFlags(mPrivateFlags);
20554        output += "}";
20555        Log.d(VIEW_LOG_TAG, output);
20556    }
20557
20558    /**
20559     * Creates a string of whitespaces used for indentation.
20560     *
20561     * @param depth the indentation level
20562     * @return a String containing (depth * 2 + 3) * 2 white spaces
20563     *
20564     * @hide
20565     */
20566    protected static String debugIndent(int depth) {
20567        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
20568        for (int i = 0; i < (depth * 2) + 3; i++) {
20569            spaces.append(' ').append(' ');
20570        }
20571        return spaces.toString();
20572    }
20573
20574    /**
20575     * <p>Return the offset of the widget's text baseline from the widget's top
20576     * boundary. If this widget does not support baseline alignment, this
20577     * method returns -1. </p>
20578     *
20579     * @return the offset of the baseline within the widget's bounds or -1
20580     *         if baseline alignment is not supported
20581     */
20582    @ViewDebug.ExportedProperty(category = "layout")
20583    public int getBaseline() {
20584        return -1;
20585    }
20586
20587    /**
20588     * Returns whether the view hierarchy is currently undergoing a layout pass. This
20589     * information is useful to avoid situations such as calling {@link #requestLayout()} during
20590     * a layout pass.
20591     *
20592     * @return whether the view hierarchy is currently undergoing a layout pass
20593     */
20594    public boolean isInLayout() {
20595        ViewRootImpl viewRoot = getViewRootImpl();
20596        return (viewRoot != null && viewRoot.isInLayout());
20597    }
20598
20599    /**
20600     * Call this when something has changed which has invalidated the
20601     * layout of this view. This will schedule a layout pass of the view
20602     * tree. This should not be called while the view hierarchy is currently in a layout
20603     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
20604     * end of the current layout pass (and then layout will run again) or after the current
20605     * frame is drawn and the next layout occurs.
20606     *
20607     * <p>Subclasses which override this method should call the superclass method to
20608     * handle possible request-during-layout errors correctly.</p>
20609     */
20610    @CallSuper
20611    public void requestLayout() {
20612        if (mMeasureCache != null) mMeasureCache.clear();
20613
20614        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
20615            // Only trigger request-during-layout logic if this is the view requesting it,
20616            // not the views in its parent hierarchy
20617            ViewRootImpl viewRoot = getViewRootImpl();
20618            if (viewRoot != null && viewRoot.isInLayout()) {
20619                if (!viewRoot.requestLayoutDuringLayout(this)) {
20620                    return;
20621                }
20622            }
20623            mAttachInfo.mViewRequestingLayout = this;
20624        }
20625
20626        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
20627        mPrivateFlags |= PFLAG_INVALIDATED;
20628
20629        if (mParent != null && !mParent.isLayoutRequested()) {
20630            mParent.requestLayout();
20631        }
20632        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
20633            mAttachInfo.mViewRequestingLayout = null;
20634        }
20635    }
20636
20637    /**
20638     * Forces this view to be laid out during the next layout pass.
20639     * This method does not call requestLayout() or forceLayout()
20640     * on the parent.
20641     */
20642    public void forceLayout() {
20643        if (mMeasureCache != null) mMeasureCache.clear();
20644
20645        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
20646        mPrivateFlags |= PFLAG_INVALIDATED;
20647    }
20648
20649    /**
20650     * <p>
20651     * This is called to find out how big a view should be. The parent
20652     * supplies constraint information in the width and height parameters.
20653     * </p>
20654     *
20655     * <p>
20656     * The actual measurement work of a view is performed in
20657     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
20658     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
20659     * </p>
20660     *
20661     *
20662     * @param widthMeasureSpec Horizontal space requirements as imposed by the
20663     *        parent
20664     * @param heightMeasureSpec Vertical space requirements as imposed by the
20665     *        parent
20666     *
20667     * @see #onMeasure(int, int)
20668     */
20669    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
20670        boolean optical = isLayoutModeOptical(this);
20671        if (optical != isLayoutModeOptical(mParent)) {
20672            Insets insets = getOpticalInsets();
20673            int oWidth  = insets.left + insets.right;
20674            int oHeight = insets.top  + insets.bottom;
20675            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
20676            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
20677        }
20678
20679        // Suppress sign extension for the low bytes
20680        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
20681        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
20682
20683        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
20684
20685        // Optimize layout by avoiding an extra EXACTLY pass when the view is
20686        // already measured as the correct size. In API 23 and below, this
20687        // extra pass is required to make LinearLayout re-distribute weight.
20688        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
20689                || heightMeasureSpec != mOldHeightMeasureSpec;
20690        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
20691                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
20692        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
20693                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
20694        final boolean needsLayout = specChanged
20695                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
20696
20697        if (forceLayout || needsLayout) {
20698            // first clears the measured dimension flag
20699            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
20700
20701            resolveRtlPropertiesIfNeeded();
20702
20703            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
20704            if (cacheIndex < 0 || sIgnoreMeasureCache) {
20705                // measure ourselves, this should set the measured dimension flag back
20706                onMeasure(widthMeasureSpec, heightMeasureSpec);
20707                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
20708            } else {
20709                long value = mMeasureCache.valueAt(cacheIndex);
20710                // Casting a long to int drops the high 32 bits, no mask needed
20711                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
20712                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
20713            }
20714
20715            // flag not set, setMeasuredDimension() was not invoked, we raise
20716            // an exception to warn the developer
20717            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
20718                throw new IllegalStateException("View with id " + getId() + ": "
20719                        + getClass().getName() + "#onMeasure() did not set the"
20720                        + " measured dimension by calling"
20721                        + " setMeasuredDimension()");
20722            }
20723
20724            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
20725        }
20726
20727        mOldWidthMeasureSpec = widthMeasureSpec;
20728        mOldHeightMeasureSpec = heightMeasureSpec;
20729
20730        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
20731                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
20732    }
20733
20734    /**
20735     * <p>
20736     * Measure the view and its content to determine the measured width and the
20737     * measured height. This method is invoked by {@link #measure(int, int)} and
20738     * should be overridden by subclasses to provide accurate and efficient
20739     * measurement of their contents.
20740     * </p>
20741     *
20742     * <p>
20743     * <strong>CONTRACT:</strong> When overriding this method, you
20744     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
20745     * measured width and height of this view. Failure to do so will trigger an
20746     * <code>IllegalStateException</code>, thrown by
20747     * {@link #measure(int, int)}. Calling the superclass'
20748     * {@link #onMeasure(int, int)} is a valid use.
20749     * </p>
20750     *
20751     * <p>
20752     * The base class implementation of measure defaults to the background size,
20753     * unless a larger size is allowed by the MeasureSpec. Subclasses should
20754     * override {@link #onMeasure(int, int)} to provide better measurements of
20755     * their content.
20756     * </p>
20757     *
20758     * <p>
20759     * If this method is overridden, it is the subclass's responsibility to make
20760     * sure the measured height and width are at least the view's minimum height
20761     * and width ({@link #getSuggestedMinimumHeight()} and
20762     * {@link #getSuggestedMinimumWidth()}).
20763     * </p>
20764     *
20765     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
20766     *                         The requirements are encoded with
20767     *                         {@link android.view.View.MeasureSpec}.
20768     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
20769     *                         The requirements are encoded with
20770     *                         {@link android.view.View.MeasureSpec}.
20771     *
20772     * @see #getMeasuredWidth()
20773     * @see #getMeasuredHeight()
20774     * @see #setMeasuredDimension(int, int)
20775     * @see #getSuggestedMinimumHeight()
20776     * @see #getSuggestedMinimumWidth()
20777     * @see android.view.View.MeasureSpec#getMode(int)
20778     * @see android.view.View.MeasureSpec#getSize(int)
20779     */
20780    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
20781        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
20782                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
20783    }
20784
20785    /**
20786     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
20787     * measured width and measured height. Failing to do so will trigger an
20788     * exception at measurement time.</p>
20789     *
20790     * @param measuredWidth The measured width of this view.  May be a complex
20791     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20792     * {@link #MEASURED_STATE_TOO_SMALL}.
20793     * @param measuredHeight The measured height of this view.  May be a complex
20794     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20795     * {@link #MEASURED_STATE_TOO_SMALL}.
20796     */
20797    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
20798        boolean optical = isLayoutModeOptical(this);
20799        if (optical != isLayoutModeOptical(mParent)) {
20800            Insets insets = getOpticalInsets();
20801            int opticalWidth  = insets.left + insets.right;
20802            int opticalHeight = insets.top  + insets.bottom;
20803
20804            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
20805            measuredHeight += optical ? opticalHeight : -opticalHeight;
20806        }
20807        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
20808    }
20809
20810    /**
20811     * Sets the measured dimension without extra processing for things like optical bounds.
20812     * Useful for reapplying consistent values that have already been cooked with adjustments
20813     * for optical bounds, etc. such as those from the measurement cache.
20814     *
20815     * @param measuredWidth The measured width of this view.  May be a complex
20816     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20817     * {@link #MEASURED_STATE_TOO_SMALL}.
20818     * @param measuredHeight The measured height of this view.  May be a complex
20819     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
20820     * {@link #MEASURED_STATE_TOO_SMALL}.
20821     */
20822    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
20823        mMeasuredWidth = measuredWidth;
20824        mMeasuredHeight = measuredHeight;
20825
20826        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
20827    }
20828
20829    /**
20830     * Merge two states as returned by {@link #getMeasuredState()}.
20831     * @param curState The current state as returned from a view or the result
20832     * of combining multiple views.
20833     * @param newState The new view state to combine.
20834     * @return Returns a new integer reflecting the combination of the two
20835     * states.
20836     */
20837    public static int combineMeasuredStates(int curState, int newState) {
20838        return curState | newState;
20839    }
20840
20841    /**
20842     * Version of {@link #resolveSizeAndState(int, int, int)}
20843     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
20844     */
20845    public static int resolveSize(int size, int measureSpec) {
20846        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
20847    }
20848
20849    /**
20850     * Utility to reconcile a desired size and state, with constraints imposed
20851     * by a MeasureSpec. Will take the desired size, unless a different size
20852     * is imposed by the constraints. The returned value is a compound integer,
20853     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
20854     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
20855     * resulting size is smaller than the size the view wants to be.
20856     *
20857     * @param size How big the view wants to be.
20858     * @param measureSpec Constraints imposed by the parent.
20859     * @param childMeasuredState Size information bit mask for the view's
20860     *                           children.
20861     * @return Size information bit mask as defined by
20862     *         {@link #MEASURED_SIZE_MASK} and
20863     *         {@link #MEASURED_STATE_TOO_SMALL}.
20864     */
20865    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
20866        final int specMode = MeasureSpec.getMode(measureSpec);
20867        final int specSize = MeasureSpec.getSize(measureSpec);
20868        final int result;
20869        switch (specMode) {
20870            case MeasureSpec.AT_MOST:
20871                if (specSize < size) {
20872                    result = specSize | MEASURED_STATE_TOO_SMALL;
20873                } else {
20874                    result = size;
20875                }
20876                break;
20877            case MeasureSpec.EXACTLY:
20878                result = specSize;
20879                break;
20880            case MeasureSpec.UNSPECIFIED:
20881            default:
20882                result = size;
20883        }
20884        return result | (childMeasuredState & MEASURED_STATE_MASK);
20885    }
20886
20887    /**
20888     * Utility to return a default size. Uses the supplied size if the
20889     * MeasureSpec imposed no constraints. Will get larger if allowed
20890     * by the MeasureSpec.
20891     *
20892     * @param size Default size for this view
20893     * @param measureSpec Constraints imposed by the parent
20894     * @return The size this view should be.
20895     */
20896    public static int getDefaultSize(int size, int measureSpec) {
20897        int result = size;
20898        int specMode = MeasureSpec.getMode(measureSpec);
20899        int specSize = MeasureSpec.getSize(measureSpec);
20900
20901        switch (specMode) {
20902        case MeasureSpec.UNSPECIFIED:
20903            result = size;
20904            break;
20905        case MeasureSpec.AT_MOST:
20906        case MeasureSpec.EXACTLY:
20907            result = specSize;
20908            break;
20909        }
20910        return result;
20911    }
20912
20913    /**
20914     * Returns the suggested minimum height that the view should use. This
20915     * returns the maximum of the view's minimum height
20916     * and the background's minimum height
20917     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
20918     * <p>
20919     * When being used in {@link #onMeasure(int, int)}, the caller should still
20920     * ensure the returned height is within the requirements of the parent.
20921     *
20922     * @return The suggested minimum height of the view.
20923     */
20924    protected int getSuggestedMinimumHeight() {
20925        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
20926
20927    }
20928
20929    /**
20930     * Returns the suggested minimum width that the view should use. This
20931     * returns the maximum of the view's minimum width
20932     * and the background's minimum width
20933     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
20934     * <p>
20935     * When being used in {@link #onMeasure(int, int)}, the caller should still
20936     * ensure the returned width is within the requirements of the parent.
20937     *
20938     * @return The suggested minimum width of the view.
20939     */
20940    protected int getSuggestedMinimumWidth() {
20941        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
20942    }
20943
20944    /**
20945     * Returns the minimum height of the view.
20946     *
20947     * @return the minimum height the view will try to be, in pixels
20948     *
20949     * @see #setMinimumHeight(int)
20950     *
20951     * @attr ref android.R.styleable#View_minHeight
20952     */
20953    public int getMinimumHeight() {
20954        return mMinHeight;
20955    }
20956
20957    /**
20958     * Sets the minimum height of the view. It is not guaranteed the view will
20959     * be able to achieve this minimum height (for example, if its parent layout
20960     * constrains it with less available height).
20961     *
20962     * @param minHeight The minimum height the view will try to be, in pixels
20963     *
20964     * @see #getMinimumHeight()
20965     *
20966     * @attr ref android.R.styleable#View_minHeight
20967     */
20968    @RemotableViewMethod
20969    public void setMinimumHeight(int minHeight) {
20970        mMinHeight = minHeight;
20971        requestLayout();
20972    }
20973
20974    /**
20975     * Returns the minimum width of the view.
20976     *
20977     * @return the minimum width the view will try to be, in pixels
20978     *
20979     * @see #setMinimumWidth(int)
20980     *
20981     * @attr ref android.R.styleable#View_minWidth
20982     */
20983    public int getMinimumWidth() {
20984        return mMinWidth;
20985    }
20986
20987    /**
20988     * Sets the minimum width of the view. It is not guaranteed the view will
20989     * be able to achieve this minimum width (for example, if its parent layout
20990     * constrains it with less available width).
20991     *
20992     * @param minWidth The minimum width the view will try to be, in pixels
20993     *
20994     * @see #getMinimumWidth()
20995     *
20996     * @attr ref android.R.styleable#View_minWidth
20997     */
20998    public void setMinimumWidth(int minWidth) {
20999        mMinWidth = minWidth;
21000        requestLayout();
21001
21002    }
21003
21004    /**
21005     * Get the animation currently associated with this view.
21006     *
21007     * @return The animation that is currently playing or
21008     *         scheduled to play for this view.
21009     */
21010    public Animation getAnimation() {
21011        return mCurrentAnimation;
21012    }
21013
21014    /**
21015     * Start the specified animation now.
21016     *
21017     * @param animation the animation to start now
21018     */
21019    public void startAnimation(Animation animation) {
21020        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
21021        setAnimation(animation);
21022        invalidateParentCaches();
21023        invalidate(true);
21024    }
21025
21026    /**
21027     * Cancels any animations for this view.
21028     */
21029    public void clearAnimation() {
21030        if (mCurrentAnimation != null) {
21031            mCurrentAnimation.detach();
21032        }
21033        mCurrentAnimation = null;
21034        invalidateParentIfNeeded();
21035    }
21036
21037    /**
21038     * Sets the next animation to play for this view.
21039     * If you want the animation to play immediately, use
21040     * {@link #startAnimation(android.view.animation.Animation)} instead.
21041     * This method provides allows fine-grained
21042     * control over the start time and invalidation, but you
21043     * must make sure that 1) the animation has a start time set, and
21044     * 2) the view's parent (which controls animations on its children)
21045     * will be invalidated when the animation is supposed to
21046     * start.
21047     *
21048     * @param animation The next animation, or null.
21049     */
21050    public void setAnimation(Animation animation) {
21051        mCurrentAnimation = animation;
21052
21053        if (animation != null) {
21054            // If the screen is off assume the animation start time is now instead of
21055            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
21056            // would cause the animation to start when the screen turns back on
21057            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
21058                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
21059                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
21060            }
21061            animation.reset();
21062        }
21063    }
21064
21065    /**
21066     * Invoked by a parent ViewGroup to notify the start of the animation
21067     * currently associated with this view. If you override this method,
21068     * always call super.onAnimationStart();
21069     *
21070     * @see #setAnimation(android.view.animation.Animation)
21071     * @see #getAnimation()
21072     */
21073    @CallSuper
21074    protected void onAnimationStart() {
21075        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
21076    }
21077
21078    /**
21079     * Invoked by a parent ViewGroup to notify the end of the animation
21080     * currently associated with this view. If you override this method,
21081     * always call super.onAnimationEnd();
21082     *
21083     * @see #setAnimation(android.view.animation.Animation)
21084     * @see #getAnimation()
21085     */
21086    @CallSuper
21087    protected void onAnimationEnd() {
21088        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
21089    }
21090
21091    /**
21092     * Invoked if there is a Transform that involves alpha. Subclass that can
21093     * draw themselves with the specified alpha should return true, and then
21094     * respect that alpha when their onDraw() is called. If this returns false
21095     * then the view may be redirected to draw into an offscreen buffer to
21096     * fulfill the request, which will look fine, but may be slower than if the
21097     * subclass handles it internally. The default implementation returns false.
21098     *
21099     * @param alpha The alpha (0..255) to apply to the view's drawing
21100     * @return true if the view can draw with the specified alpha.
21101     */
21102    protected boolean onSetAlpha(int alpha) {
21103        return false;
21104    }
21105
21106    /**
21107     * This is used by the RootView to perform an optimization when
21108     * the view hierarchy contains one or several SurfaceView.
21109     * SurfaceView is always considered transparent, but its children are not,
21110     * therefore all View objects remove themselves from the global transparent
21111     * region (passed as a parameter to this function).
21112     *
21113     * @param region The transparent region for this ViewAncestor (window).
21114     *
21115     * @return Returns true if the effective visibility of the view at this
21116     * point is opaque, regardless of the transparent region; returns false
21117     * if it is possible for underlying windows to be seen behind the view.
21118     *
21119     * {@hide}
21120     */
21121    public boolean gatherTransparentRegion(Region region) {
21122        final AttachInfo attachInfo = mAttachInfo;
21123        if (region != null && attachInfo != null) {
21124            final int pflags = mPrivateFlags;
21125            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
21126                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
21127                // remove it from the transparent region.
21128                final int[] location = attachInfo.mTransparentLocation;
21129                getLocationInWindow(location);
21130                // When a view has Z value, then it will be better to leave some area below the view
21131                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
21132                // the bottom part needs more offset than the left, top and right parts due to the
21133                // spot light effects.
21134                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
21135                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
21136                        location[0] + mRight - mLeft + shadowOffset,
21137                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
21138            } else {
21139                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
21140                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
21141                    // the background drawable's non-transparent parts from this transparent region.
21142                    applyDrawableToTransparentRegion(mBackground, region);
21143                }
21144                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
21145                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
21146                    // Similarly, we remove the foreground drawable's non-transparent parts.
21147                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
21148                }
21149            }
21150        }
21151        return true;
21152    }
21153
21154    /**
21155     * Play a sound effect for this view.
21156     *
21157     * <p>The framework will play sound effects for some built in actions, such as
21158     * clicking, but you may wish to play these effects in your widget,
21159     * for instance, for internal navigation.
21160     *
21161     * <p>The sound effect will only be played if sound effects are enabled by the user, and
21162     * {@link #isSoundEffectsEnabled()} is true.
21163     *
21164     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
21165     */
21166    public void playSoundEffect(int soundConstant) {
21167        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
21168            return;
21169        }
21170        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
21171    }
21172
21173    /**
21174     * BZZZTT!!1!
21175     *
21176     * <p>Provide haptic feedback to the user for this view.
21177     *
21178     * <p>The framework will provide haptic feedback for some built in actions,
21179     * such as long presses, but you may wish to provide feedback for your
21180     * own widget.
21181     *
21182     * <p>The feedback will only be performed if
21183     * {@link #isHapticFeedbackEnabled()} is true.
21184     *
21185     * @param feedbackConstant One of the constants defined in
21186     * {@link HapticFeedbackConstants}
21187     */
21188    public boolean performHapticFeedback(int feedbackConstant) {
21189        return performHapticFeedback(feedbackConstant, 0);
21190    }
21191
21192    /**
21193     * BZZZTT!!1!
21194     *
21195     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
21196     *
21197     * @param feedbackConstant One of the constants defined in
21198     * {@link HapticFeedbackConstants}
21199     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
21200     */
21201    public boolean performHapticFeedback(int feedbackConstant, int flags) {
21202        if (mAttachInfo == null) {
21203            return false;
21204        }
21205        //noinspection SimplifiableIfStatement
21206        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
21207                && !isHapticFeedbackEnabled()) {
21208            return false;
21209        }
21210        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
21211                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
21212    }
21213
21214    /**
21215     * Request that the visibility of the status bar or other screen/window
21216     * decorations be changed.
21217     *
21218     * <p>This method is used to put the over device UI into temporary modes
21219     * where the user's attention is focused more on the application content,
21220     * by dimming or hiding surrounding system affordances.  This is typically
21221     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
21222     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
21223     * to be placed behind the action bar (and with these flags other system
21224     * affordances) so that smooth transitions between hiding and showing them
21225     * can be done.
21226     *
21227     * <p>Two representative examples of the use of system UI visibility is
21228     * implementing a content browsing application (like a magazine reader)
21229     * and a video playing application.
21230     *
21231     * <p>The first code shows a typical implementation of a View in a content
21232     * browsing application.  In this implementation, the application goes
21233     * into a content-oriented mode by hiding the status bar and action bar,
21234     * and putting the navigation elements into lights out mode.  The user can
21235     * then interact with content while in this mode.  Such an application should
21236     * provide an easy way for the user to toggle out of the mode (such as to
21237     * check information in the status bar or access notifications).  In the
21238     * implementation here, this is done simply by tapping on the content.
21239     *
21240     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
21241     *      content}
21242     *
21243     * <p>This second code sample shows a typical implementation of a View
21244     * in a video playing application.  In this situation, while the video is
21245     * playing the application would like to go into a complete full-screen mode,
21246     * to use as much of the display as possible for the video.  When in this state
21247     * the user can not interact with the application; the system intercepts
21248     * touching on the screen to pop the UI out of full screen mode.  See
21249     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
21250     *
21251     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
21252     *      content}
21253     *
21254     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21255     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
21256     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
21257     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
21258     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
21259     */
21260    public void setSystemUiVisibility(int visibility) {
21261        if (visibility != mSystemUiVisibility) {
21262            mSystemUiVisibility = visibility;
21263            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
21264                mParent.recomputeViewAttributes(this);
21265            }
21266        }
21267    }
21268
21269    /**
21270     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
21271     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21272     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
21273     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
21274     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
21275     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
21276     */
21277    public int getSystemUiVisibility() {
21278        return mSystemUiVisibility;
21279    }
21280
21281    /**
21282     * Returns the current system UI visibility that is currently set for
21283     * the entire window.  This is the combination of the
21284     * {@link #setSystemUiVisibility(int)} values supplied by all of the
21285     * views in the window.
21286     */
21287    public int getWindowSystemUiVisibility() {
21288        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
21289    }
21290
21291    /**
21292     * Override to find out when the window's requested system UI visibility
21293     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
21294     * This is different from the callbacks received through
21295     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
21296     * in that this is only telling you about the local request of the window,
21297     * not the actual values applied by the system.
21298     */
21299    public void onWindowSystemUiVisibilityChanged(int visible) {
21300    }
21301
21302    /**
21303     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
21304     * the view hierarchy.
21305     */
21306    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
21307        onWindowSystemUiVisibilityChanged(visible);
21308    }
21309
21310    /**
21311     * Set a listener to receive callbacks when the visibility of the system bar changes.
21312     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
21313     */
21314    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
21315        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
21316        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
21317            mParent.recomputeViewAttributes(this);
21318        }
21319    }
21320
21321    /**
21322     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
21323     * the view hierarchy.
21324     */
21325    public void dispatchSystemUiVisibilityChanged(int visibility) {
21326        ListenerInfo li = mListenerInfo;
21327        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
21328            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
21329                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
21330        }
21331    }
21332
21333    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
21334        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
21335        if (val != mSystemUiVisibility) {
21336            setSystemUiVisibility(val);
21337            return true;
21338        }
21339        return false;
21340    }
21341
21342    /** @hide */
21343    public void setDisabledSystemUiVisibility(int flags) {
21344        if (mAttachInfo != null) {
21345            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
21346                mAttachInfo.mDisabledSystemUiVisibility = flags;
21347                if (mParent != null) {
21348                    mParent.recomputeViewAttributes(this);
21349                }
21350            }
21351        }
21352    }
21353
21354    /**
21355     * Creates an image that the system displays during the drag and drop
21356     * operation. This is called a &quot;drag shadow&quot;. The default implementation
21357     * for a DragShadowBuilder based on a View returns an image that has exactly the same
21358     * appearance as the given View. The default also positions the center of the drag shadow
21359     * directly under the touch point. If no View is provided (the constructor with no parameters
21360     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
21361     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
21362     * default is an invisible drag shadow.
21363     * <p>
21364     * You are not required to use the View you provide to the constructor as the basis of the
21365     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
21366     * anything you want as the drag shadow.
21367     * </p>
21368     * <p>
21369     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
21370     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
21371     *  size and position of the drag shadow. It uses this data to construct a
21372     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
21373     *  so that your application can draw the shadow image in the Canvas.
21374     * </p>
21375     *
21376     * <div class="special reference">
21377     * <h3>Developer Guides</h3>
21378     * <p>For a guide to implementing drag and drop features, read the
21379     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21380     * </div>
21381     */
21382    public static class DragShadowBuilder {
21383        private final WeakReference<View> mView;
21384
21385        /**
21386         * Constructs a shadow image builder based on a View. By default, the resulting drag
21387         * shadow will have the same appearance and dimensions as the View, with the touch point
21388         * over the center of the View.
21389         * @param view A View. Any View in scope can be used.
21390         */
21391        public DragShadowBuilder(View view) {
21392            mView = new WeakReference<View>(view);
21393        }
21394
21395        /**
21396         * Construct a shadow builder object with no associated View.  This
21397         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
21398         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
21399         * to supply the drag shadow's dimensions and appearance without
21400         * reference to any View object. If they are not overridden, then the result is an
21401         * invisible drag shadow.
21402         */
21403        public DragShadowBuilder() {
21404            mView = new WeakReference<View>(null);
21405        }
21406
21407        /**
21408         * Returns the View object that had been passed to the
21409         * {@link #View.DragShadowBuilder(View)}
21410         * constructor.  If that View parameter was {@code null} or if the
21411         * {@link #View.DragShadowBuilder()}
21412         * constructor was used to instantiate the builder object, this method will return
21413         * null.
21414         *
21415         * @return The View object associate with this builder object.
21416         */
21417        @SuppressWarnings({"JavadocReference"})
21418        final public View getView() {
21419            return mView.get();
21420        }
21421
21422        /**
21423         * Provides the metrics for the shadow image. These include the dimensions of
21424         * the shadow image, and the point within that shadow that should
21425         * be centered under the touch location while dragging.
21426         * <p>
21427         * The default implementation sets the dimensions of the shadow to be the
21428         * same as the dimensions of the View itself and centers the shadow under
21429         * the touch point.
21430         * </p>
21431         *
21432         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
21433         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
21434         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
21435         * image.
21436         *
21437         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
21438         * shadow image that should be underneath the touch point during the drag and drop
21439         * operation. Your application must set {@link android.graphics.Point#x} to the
21440         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
21441         */
21442        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
21443            final View view = mView.get();
21444            if (view != null) {
21445                outShadowSize.set(view.getWidth(), view.getHeight());
21446                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
21447            } else {
21448                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
21449            }
21450        }
21451
21452        /**
21453         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
21454         * based on the dimensions it received from the
21455         * {@link #onProvideShadowMetrics(Point, Point)} callback.
21456         *
21457         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
21458         */
21459        public void onDrawShadow(Canvas canvas) {
21460            final View view = mView.get();
21461            if (view != null) {
21462                view.draw(canvas);
21463            } else {
21464                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
21465            }
21466        }
21467    }
21468
21469    /**
21470     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
21471     * startDragAndDrop()} for newer platform versions.
21472     */
21473    @Deprecated
21474    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
21475                                   Object myLocalState, int flags) {
21476        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
21477    }
21478
21479    /**
21480     * Starts a drag and drop operation. When your application calls this method, it passes a
21481     * {@link android.view.View.DragShadowBuilder} object to the system. The
21482     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
21483     * to get metrics for the drag shadow, and then calls the object's
21484     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
21485     * <p>
21486     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
21487     *  drag events to all the View objects in your application that are currently visible. It does
21488     *  this either by calling the View object's drag listener (an implementation of
21489     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
21490     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
21491     *  Both are passed a {@link android.view.DragEvent} object that has a
21492     *  {@link android.view.DragEvent#getAction()} value of
21493     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
21494     * </p>
21495     * <p>
21496     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
21497     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
21498     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
21499     * to the View the user selected for dragging.
21500     * </p>
21501     * @param data A {@link android.content.ClipData} object pointing to the data to be
21502     * transferred by the drag and drop operation.
21503     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
21504     * drag shadow.
21505     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
21506     * drop operation. When dispatching drag events to views in the same activity this object
21507     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
21508     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
21509     * will return null).
21510     * <p>
21511     * myLocalState is a lightweight mechanism for the sending information from the dragged View
21512     * to the target Views. For example, it can contain flags that differentiate between a
21513     * a copy operation and a move operation.
21514     * </p>
21515     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
21516     * flags, or any combination of the following:
21517     *     <ul>
21518     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
21519     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
21520     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
21521     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
21522     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
21523     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
21524     *     </ul>
21525     * @return {@code true} if the method completes successfully, or
21526     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
21527     * do a drag, and so no drag operation is in progress.
21528     */
21529    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
21530            Object myLocalState, int flags) {
21531        if (ViewDebug.DEBUG_DRAG) {
21532            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
21533        }
21534        if (mAttachInfo == null) {
21535            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
21536            return false;
21537        }
21538
21539        if (data != null) {
21540            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
21541        }
21542
21543        boolean okay = false;
21544
21545        Point shadowSize = new Point();
21546        Point shadowTouchPoint = new Point();
21547        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
21548
21549        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
21550                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
21551            throw new IllegalStateException("Drag shadow dimensions must not be negative");
21552        }
21553
21554        if (ViewDebug.DEBUG_DRAG) {
21555            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
21556                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
21557        }
21558        if (mAttachInfo.mDragSurface != null) {
21559            mAttachInfo.mDragSurface.release();
21560        }
21561        mAttachInfo.mDragSurface = new Surface();
21562        try {
21563            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
21564                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
21565            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
21566                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
21567            if (mAttachInfo.mDragToken != null) {
21568                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
21569                try {
21570                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
21571                    shadowBuilder.onDrawShadow(canvas);
21572                } finally {
21573                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
21574                }
21575
21576                final ViewRootImpl root = getViewRootImpl();
21577
21578                // Cache the local state object for delivery with DragEvents
21579                root.setLocalDragState(myLocalState);
21580
21581                // repurpose 'shadowSize' for the last touch point
21582                root.getLastTouchPoint(shadowSize);
21583
21584                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
21585                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
21586                        shadowTouchPoint.x, shadowTouchPoint.y, data);
21587                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
21588            }
21589        } catch (Exception e) {
21590            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
21591            mAttachInfo.mDragSurface.destroy();
21592            mAttachInfo.mDragSurface = null;
21593        }
21594
21595        return okay;
21596    }
21597
21598    /**
21599     * Cancels an ongoing drag and drop operation.
21600     * <p>
21601     * A {@link android.view.DragEvent} object with
21602     * {@link android.view.DragEvent#getAction()} value of
21603     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
21604     * {@link android.view.DragEvent#getResult()} value of {@code false}
21605     * will be sent to every
21606     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
21607     * even if they are not currently visible.
21608     * </p>
21609     * <p>
21610     * This method can be called on any View in the same window as the View on which
21611     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
21612     * was called.
21613     * </p>
21614     */
21615    public final void cancelDragAndDrop() {
21616        if (ViewDebug.DEBUG_DRAG) {
21617            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
21618        }
21619        if (mAttachInfo == null) {
21620            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
21621            return;
21622        }
21623        if (mAttachInfo.mDragToken != null) {
21624            try {
21625                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
21626            } catch (Exception e) {
21627                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
21628            }
21629            mAttachInfo.mDragToken = null;
21630        } else {
21631            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
21632        }
21633    }
21634
21635    /**
21636     * Updates the drag shadow for the ongoing drag and drop operation.
21637     *
21638     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
21639     * new drag shadow.
21640     */
21641    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
21642        if (ViewDebug.DEBUG_DRAG) {
21643            Log.d(VIEW_LOG_TAG, "updateDragShadow");
21644        }
21645        if (mAttachInfo == null) {
21646            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
21647            return;
21648        }
21649        if (mAttachInfo.mDragToken != null) {
21650            try {
21651                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
21652                try {
21653                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
21654                    shadowBuilder.onDrawShadow(canvas);
21655                } finally {
21656                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
21657                }
21658            } catch (Exception e) {
21659                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
21660            }
21661        } else {
21662            Log.e(VIEW_LOG_TAG, "No active drag");
21663        }
21664    }
21665
21666    /**
21667     * Starts a move from {startX, startY}, the amount of the movement will be the offset
21668     * between {startX, startY} and the new cursor positon.
21669     * @param startX horizontal coordinate where the move started.
21670     * @param startY vertical coordinate where the move started.
21671     * @return whether moving was started successfully.
21672     * @hide
21673     */
21674    public final boolean startMovingTask(float startX, float startY) {
21675        if (ViewDebug.DEBUG_POSITIONING) {
21676            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
21677        }
21678        try {
21679            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
21680        } catch (RemoteException e) {
21681            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
21682        }
21683        return false;
21684    }
21685
21686    /**
21687     * Handles drag events sent by the system following a call to
21688     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
21689     * startDragAndDrop()}.
21690     *<p>
21691     * When the system calls this method, it passes a
21692     * {@link android.view.DragEvent} object. A call to
21693     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
21694     * in DragEvent. The method uses these to determine what is happening in the drag and drop
21695     * operation.
21696     * @param event The {@link android.view.DragEvent} sent by the system.
21697     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
21698     * in DragEvent, indicating the type of drag event represented by this object.
21699     * @return {@code true} if the method was successful, otherwise {@code false}.
21700     * <p>
21701     *  The method should return {@code true} in response to an action type of
21702     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
21703     *  operation.
21704     * </p>
21705     * <p>
21706     *  The method should also return {@code true} in response to an action type of
21707     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
21708     *  {@code false} if it didn't.
21709     * </p>
21710     * <p>
21711     *  For all other events, the return value is ignored.
21712     * </p>
21713     */
21714    public boolean onDragEvent(DragEvent event) {
21715        return false;
21716    }
21717
21718    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
21719    boolean dispatchDragEnterExitInPreN(DragEvent event) {
21720        return callDragEventHandler(event);
21721    }
21722
21723    /**
21724     * Detects if this View is enabled and has a drag event listener.
21725     * If both are true, then it calls the drag event listener with the
21726     * {@link android.view.DragEvent} it received. If the drag event listener returns
21727     * {@code true}, then dispatchDragEvent() returns {@code true}.
21728     * <p>
21729     * For all other cases, the method calls the
21730     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
21731     * method and returns its result.
21732     * </p>
21733     * <p>
21734     * This ensures that a drag event is always consumed, even if the View does not have a drag
21735     * event listener. However, if the View has a listener and the listener returns true, then
21736     * onDragEvent() is not called.
21737     * </p>
21738     */
21739    public boolean dispatchDragEvent(DragEvent event) {
21740        event.mEventHandlerWasCalled = true;
21741        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
21742            event.mAction == DragEvent.ACTION_DROP) {
21743            // About to deliver an event with coordinates to this view. Notify that now this view
21744            // has drag focus. This will send exit/enter events as needed.
21745            getViewRootImpl().setDragFocus(this, event);
21746        }
21747        return callDragEventHandler(event);
21748    }
21749
21750    final boolean callDragEventHandler(DragEvent event) {
21751        final boolean result;
21752
21753        ListenerInfo li = mListenerInfo;
21754        //noinspection SimplifiableIfStatement
21755        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
21756                && li.mOnDragListener.onDrag(this, event)) {
21757            result = true;
21758        } else {
21759            result = onDragEvent(event);
21760        }
21761
21762        switch (event.mAction) {
21763            case DragEvent.ACTION_DRAG_ENTERED: {
21764                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
21765                refreshDrawableState();
21766            } break;
21767            case DragEvent.ACTION_DRAG_EXITED: {
21768                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
21769                refreshDrawableState();
21770            } break;
21771            case DragEvent.ACTION_DRAG_ENDED: {
21772                mPrivateFlags2 &= ~View.DRAG_MASK;
21773                refreshDrawableState();
21774            } break;
21775        }
21776
21777        return result;
21778    }
21779
21780    boolean canAcceptDrag() {
21781        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
21782    }
21783
21784    /**
21785     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
21786     * it is ever exposed at all.
21787     * @hide
21788     */
21789    public void onCloseSystemDialogs(String reason) {
21790    }
21791
21792    /**
21793     * Given a Drawable whose bounds have been set to draw into this view,
21794     * update a Region being computed for
21795     * {@link #gatherTransparentRegion(android.graphics.Region)} so
21796     * that any non-transparent parts of the Drawable are removed from the
21797     * given transparent region.
21798     *
21799     * @param dr The Drawable whose transparency is to be applied to the region.
21800     * @param region A Region holding the current transparency information,
21801     * where any parts of the region that are set are considered to be
21802     * transparent.  On return, this region will be modified to have the
21803     * transparency information reduced by the corresponding parts of the
21804     * Drawable that are not transparent.
21805     * {@hide}
21806     */
21807    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
21808        if (DBG) {
21809            Log.i("View", "Getting transparent region for: " + this);
21810        }
21811        final Region r = dr.getTransparentRegion();
21812        final Rect db = dr.getBounds();
21813        final AttachInfo attachInfo = mAttachInfo;
21814        if (r != null && attachInfo != null) {
21815            final int w = getRight()-getLeft();
21816            final int h = getBottom()-getTop();
21817            if (db.left > 0) {
21818                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
21819                r.op(0, 0, db.left, h, Region.Op.UNION);
21820            }
21821            if (db.right < w) {
21822                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
21823                r.op(db.right, 0, w, h, Region.Op.UNION);
21824            }
21825            if (db.top > 0) {
21826                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
21827                r.op(0, 0, w, db.top, Region.Op.UNION);
21828            }
21829            if (db.bottom < h) {
21830                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
21831                r.op(0, db.bottom, w, h, Region.Op.UNION);
21832            }
21833            final int[] location = attachInfo.mTransparentLocation;
21834            getLocationInWindow(location);
21835            r.translate(location[0], location[1]);
21836            region.op(r, Region.Op.INTERSECT);
21837        } else {
21838            region.op(db, Region.Op.DIFFERENCE);
21839        }
21840    }
21841
21842    private void checkForLongClick(int delayOffset, float x, float y) {
21843        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
21844            mHasPerformedLongPress = false;
21845
21846            if (mPendingCheckForLongPress == null) {
21847                mPendingCheckForLongPress = new CheckForLongPress();
21848            }
21849            mPendingCheckForLongPress.setAnchor(x, y);
21850            mPendingCheckForLongPress.rememberWindowAttachCount();
21851            mPendingCheckForLongPress.rememberPressedState();
21852            postDelayed(mPendingCheckForLongPress,
21853                    ViewConfiguration.getLongPressTimeout() - delayOffset);
21854        }
21855    }
21856
21857    /**
21858     * Inflate a view from an XML resource.  This convenience method wraps the {@link
21859     * LayoutInflater} class, which provides a full range of options for view inflation.
21860     *
21861     * @param context The Context object for your activity or application.
21862     * @param resource The resource ID to inflate
21863     * @param root A view group that will be the parent.  Used to properly inflate the
21864     * layout_* parameters.
21865     * @see LayoutInflater
21866     */
21867    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
21868        LayoutInflater factory = LayoutInflater.from(context);
21869        return factory.inflate(resource, root);
21870    }
21871
21872    /**
21873     * Scroll the view with standard behavior for scrolling beyond the normal
21874     * content boundaries. Views that call this method should override
21875     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
21876     * results of an over-scroll operation.
21877     *
21878     * Views can use this method to handle any touch or fling-based scrolling.
21879     *
21880     * @param deltaX Change in X in pixels
21881     * @param deltaY Change in Y in pixels
21882     * @param scrollX Current X scroll value in pixels before applying deltaX
21883     * @param scrollY Current Y scroll value in pixels before applying deltaY
21884     * @param scrollRangeX Maximum content scroll range along the X axis
21885     * @param scrollRangeY Maximum content scroll range along the Y axis
21886     * @param maxOverScrollX Number of pixels to overscroll by in either direction
21887     *          along the X axis.
21888     * @param maxOverScrollY Number of pixels to overscroll by in either direction
21889     *          along the Y axis.
21890     * @param isTouchEvent true if this scroll operation is the result of a touch event.
21891     * @return true if scrolling was clamped to an over-scroll boundary along either
21892     *          axis, false otherwise.
21893     */
21894    @SuppressWarnings({"UnusedParameters"})
21895    protected boolean overScrollBy(int deltaX, int deltaY,
21896            int scrollX, int scrollY,
21897            int scrollRangeX, int scrollRangeY,
21898            int maxOverScrollX, int maxOverScrollY,
21899            boolean isTouchEvent) {
21900        final int overScrollMode = mOverScrollMode;
21901        final boolean canScrollHorizontal =
21902                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
21903        final boolean canScrollVertical =
21904                computeVerticalScrollRange() > computeVerticalScrollExtent();
21905        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
21906                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
21907        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
21908                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
21909
21910        int newScrollX = scrollX + deltaX;
21911        if (!overScrollHorizontal) {
21912            maxOverScrollX = 0;
21913        }
21914
21915        int newScrollY = scrollY + deltaY;
21916        if (!overScrollVertical) {
21917            maxOverScrollY = 0;
21918        }
21919
21920        // Clamp values if at the limits and record
21921        final int left = -maxOverScrollX;
21922        final int right = maxOverScrollX + scrollRangeX;
21923        final int top = -maxOverScrollY;
21924        final int bottom = maxOverScrollY + scrollRangeY;
21925
21926        boolean clampedX = false;
21927        if (newScrollX > right) {
21928            newScrollX = right;
21929            clampedX = true;
21930        } else if (newScrollX < left) {
21931            newScrollX = left;
21932            clampedX = true;
21933        }
21934
21935        boolean clampedY = false;
21936        if (newScrollY > bottom) {
21937            newScrollY = bottom;
21938            clampedY = true;
21939        } else if (newScrollY < top) {
21940            newScrollY = top;
21941            clampedY = true;
21942        }
21943
21944        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
21945
21946        return clampedX || clampedY;
21947    }
21948
21949    /**
21950     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
21951     * respond to the results of an over-scroll operation.
21952     *
21953     * @param scrollX New X scroll value in pixels
21954     * @param scrollY New Y scroll value in pixels
21955     * @param clampedX True if scrollX was clamped to an over-scroll boundary
21956     * @param clampedY True if scrollY was clamped to an over-scroll boundary
21957     */
21958    protected void onOverScrolled(int scrollX, int scrollY,
21959            boolean clampedX, boolean clampedY) {
21960        // Intentionally empty.
21961    }
21962
21963    /**
21964     * Returns the over-scroll mode for this view. The result will be
21965     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21966     * (allow over-scrolling only if the view content is larger than the container),
21967     * or {@link #OVER_SCROLL_NEVER}.
21968     *
21969     * @return This view's over-scroll mode.
21970     */
21971    public int getOverScrollMode() {
21972        return mOverScrollMode;
21973    }
21974
21975    /**
21976     * Set the over-scroll mode for this view. Valid over-scroll modes are
21977     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
21978     * (allow over-scrolling only if the view content is larger than the container),
21979     * or {@link #OVER_SCROLL_NEVER}.
21980     *
21981     * Setting the over-scroll mode of a view will have an effect only if the
21982     * view is capable of scrolling.
21983     *
21984     * @param overScrollMode The new over-scroll mode for this view.
21985     */
21986    public void setOverScrollMode(int overScrollMode) {
21987        if (overScrollMode != OVER_SCROLL_ALWAYS &&
21988                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
21989                overScrollMode != OVER_SCROLL_NEVER) {
21990            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
21991        }
21992        mOverScrollMode = overScrollMode;
21993    }
21994
21995    /**
21996     * Enable or disable nested scrolling for this view.
21997     *
21998     * <p>If this property is set to true the view will be permitted to initiate nested
21999     * scrolling operations with a compatible parent view in the current hierarchy. If this
22000     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
22001     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
22002     * the nested scroll.</p>
22003     *
22004     * @param enabled true to enable nested scrolling, false to disable
22005     *
22006     * @see #isNestedScrollingEnabled()
22007     */
22008    public void setNestedScrollingEnabled(boolean enabled) {
22009        if (enabled) {
22010            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
22011        } else {
22012            stopNestedScroll();
22013            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
22014        }
22015    }
22016
22017    /**
22018     * Returns true if nested scrolling is enabled for this view.
22019     *
22020     * <p>If nested scrolling is enabled and this View class implementation supports it,
22021     * this view will act as a nested scrolling child view when applicable, forwarding data
22022     * about the scroll operation in progress to a compatible and cooperating nested scrolling
22023     * parent.</p>
22024     *
22025     * @return true if nested scrolling is enabled
22026     *
22027     * @see #setNestedScrollingEnabled(boolean)
22028     */
22029    public boolean isNestedScrollingEnabled() {
22030        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
22031                PFLAG3_NESTED_SCROLLING_ENABLED;
22032    }
22033
22034    /**
22035     * Begin a nestable scroll operation along the given axes.
22036     *
22037     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
22038     *
22039     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
22040     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
22041     * In the case of touch scrolling the nested scroll will be terminated automatically in
22042     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
22043     * In the event of programmatic scrolling the caller must explicitly call
22044     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
22045     *
22046     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
22047     * If it returns false the caller may ignore the rest of this contract until the next scroll.
22048     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
22049     *
22050     * <p>At each incremental step of the scroll the caller should invoke
22051     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
22052     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
22053     * parent at least partially consumed the scroll and the caller should adjust the amount it
22054     * scrolls by.</p>
22055     *
22056     * <p>After applying the remainder of the scroll delta the caller should invoke
22057     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
22058     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
22059     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
22060     * </p>
22061     *
22062     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
22063     *             {@link #SCROLL_AXIS_VERTICAL}.
22064     * @return true if a cooperative parent was found and nested scrolling has been enabled for
22065     *         the current gesture.
22066     *
22067     * @see #stopNestedScroll()
22068     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22069     * @see #dispatchNestedScroll(int, int, int, int, int[])
22070     */
22071    public boolean startNestedScroll(int axes) {
22072        if (hasNestedScrollingParent()) {
22073            // Already in progress
22074            return true;
22075        }
22076        if (isNestedScrollingEnabled()) {
22077            ViewParent p = getParent();
22078            View child = this;
22079            while (p != null) {
22080                try {
22081                    if (p.onStartNestedScroll(child, this, axes)) {
22082                        mNestedScrollingParent = p;
22083                        p.onNestedScrollAccepted(child, this, axes);
22084                        return true;
22085                    }
22086                } catch (AbstractMethodError e) {
22087                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
22088                            "method onStartNestedScroll", e);
22089                    // Allow the search upward to continue
22090                }
22091                if (p instanceof View) {
22092                    child = (View) p;
22093                }
22094                p = p.getParent();
22095            }
22096        }
22097        return false;
22098    }
22099
22100    /**
22101     * Stop a nested scroll in progress.
22102     *
22103     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
22104     *
22105     * @see #startNestedScroll(int)
22106     */
22107    public void stopNestedScroll() {
22108        if (mNestedScrollingParent != null) {
22109            mNestedScrollingParent.onStopNestedScroll(this);
22110            mNestedScrollingParent = null;
22111        }
22112    }
22113
22114    /**
22115     * Returns true if this view has a nested scrolling parent.
22116     *
22117     * <p>The presence of a nested scrolling parent indicates that this view has initiated
22118     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
22119     *
22120     * @return whether this view has a nested scrolling parent
22121     */
22122    public boolean hasNestedScrollingParent() {
22123        return mNestedScrollingParent != null;
22124    }
22125
22126    /**
22127     * Dispatch one step of a nested scroll in progress.
22128     *
22129     * <p>Implementations of views that support nested scrolling should call this to report
22130     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
22131     * is not currently in progress or nested scrolling is not
22132     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
22133     *
22134     * <p>Compatible View implementations should also call
22135     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
22136     * consuming a component of the scroll event themselves.</p>
22137     *
22138     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
22139     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
22140     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
22141     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
22142     * @param offsetInWindow Optional. If not null, on return this will contain the offset
22143     *                       in local view coordinates of this view from before this operation
22144     *                       to after it completes. View implementations may use this to adjust
22145     *                       expected input coordinate tracking.
22146     * @return true if the event was dispatched, false if it could not be dispatched.
22147     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22148     */
22149    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
22150            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
22151        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22152            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
22153                int startX = 0;
22154                int startY = 0;
22155                if (offsetInWindow != null) {
22156                    getLocationInWindow(offsetInWindow);
22157                    startX = offsetInWindow[0];
22158                    startY = offsetInWindow[1];
22159                }
22160
22161                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
22162                        dxUnconsumed, dyUnconsumed);
22163
22164                if (offsetInWindow != null) {
22165                    getLocationInWindow(offsetInWindow);
22166                    offsetInWindow[0] -= startX;
22167                    offsetInWindow[1] -= startY;
22168                }
22169                return true;
22170            } else if (offsetInWindow != null) {
22171                // No motion, no dispatch. Keep offsetInWindow up to date.
22172                offsetInWindow[0] = 0;
22173                offsetInWindow[1] = 0;
22174            }
22175        }
22176        return false;
22177    }
22178
22179    /**
22180     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
22181     *
22182     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
22183     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
22184     * scrolling operation to consume some or all of the scroll operation before the child view
22185     * consumes it.</p>
22186     *
22187     * @param dx Horizontal scroll distance in pixels
22188     * @param dy Vertical scroll distance in pixels
22189     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
22190     *                 and consumed[1] the consumed dy.
22191     * @param offsetInWindow Optional. If not null, on return this will contain the offset
22192     *                       in local view coordinates of this view from before this operation
22193     *                       to after it completes. View implementations may use this to adjust
22194     *                       expected input coordinate tracking.
22195     * @return true if the parent consumed some or all of the scroll delta
22196     * @see #dispatchNestedScroll(int, int, int, int, int[])
22197     */
22198    public boolean dispatchNestedPreScroll(int dx, int dy,
22199            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
22200        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22201            if (dx != 0 || dy != 0) {
22202                int startX = 0;
22203                int startY = 0;
22204                if (offsetInWindow != null) {
22205                    getLocationInWindow(offsetInWindow);
22206                    startX = offsetInWindow[0];
22207                    startY = offsetInWindow[1];
22208                }
22209
22210                if (consumed == null) {
22211                    if (mTempNestedScrollConsumed == null) {
22212                        mTempNestedScrollConsumed = new int[2];
22213                    }
22214                    consumed = mTempNestedScrollConsumed;
22215                }
22216                consumed[0] = 0;
22217                consumed[1] = 0;
22218                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
22219
22220                if (offsetInWindow != null) {
22221                    getLocationInWindow(offsetInWindow);
22222                    offsetInWindow[0] -= startX;
22223                    offsetInWindow[1] -= startY;
22224                }
22225                return consumed[0] != 0 || consumed[1] != 0;
22226            } else if (offsetInWindow != null) {
22227                offsetInWindow[0] = 0;
22228                offsetInWindow[1] = 0;
22229            }
22230        }
22231        return false;
22232    }
22233
22234    /**
22235     * Dispatch a fling to a nested scrolling parent.
22236     *
22237     * <p>This method should be used to indicate that a nested scrolling child has detected
22238     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
22239     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
22240     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
22241     * along a scrollable axis.</p>
22242     *
22243     * <p>If a nested scrolling child view would normally fling but it is at the edge of
22244     * its own content, it can use this method to delegate the fling to its nested scrolling
22245     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
22246     *
22247     * @param velocityX Horizontal fling velocity in pixels per second
22248     * @param velocityY Vertical fling velocity in pixels per second
22249     * @param consumed true if the child consumed the fling, false otherwise
22250     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
22251     */
22252    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
22253        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22254            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
22255        }
22256        return false;
22257    }
22258
22259    /**
22260     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
22261     *
22262     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
22263     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
22264     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
22265     * before the child view consumes it. If this method returns <code>true</code>, a nested
22266     * parent view consumed the fling and this view should not scroll as a result.</p>
22267     *
22268     * <p>For a better user experience, only one view in a nested scrolling chain should consume
22269     * the fling at a time. If a parent view consumed the fling this method will return false.
22270     * Custom view implementations should account for this in two ways:</p>
22271     *
22272     * <ul>
22273     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
22274     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
22275     *     position regardless.</li>
22276     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
22277     *     even to settle back to a valid idle position.</li>
22278     * </ul>
22279     *
22280     * <p>Views should also not offer fling velocities to nested parent views along an axis
22281     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
22282     * should not offer a horizontal fling velocity to its parents since scrolling along that
22283     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
22284     *
22285     * @param velocityX Horizontal fling velocity in pixels per second
22286     * @param velocityY Vertical fling velocity in pixels per second
22287     * @return true if a nested scrolling parent consumed the fling
22288     */
22289    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
22290        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
22291            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
22292        }
22293        return false;
22294    }
22295
22296    /**
22297     * Gets a scale factor that determines the distance the view should scroll
22298     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
22299     * @return The vertical scroll scale factor.
22300     * @hide
22301     */
22302    protected float getVerticalScrollFactor() {
22303        if (mVerticalScrollFactor == 0) {
22304            TypedValue outValue = new TypedValue();
22305            if (!mContext.getTheme().resolveAttribute(
22306                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
22307                throw new IllegalStateException(
22308                        "Expected theme to define listPreferredItemHeight.");
22309            }
22310            mVerticalScrollFactor = outValue.getDimension(
22311                    mContext.getResources().getDisplayMetrics());
22312        }
22313        return mVerticalScrollFactor;
22314    }
22315
22316    /**
22317     * Gets a scale factor that determines the distance the view should scroll
22318     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
22319     * @return The horizontal scroll scale factor.
22320     * @hide
22321     */
22322    protected float getHorizontalScrollFactor() {
22323        // TODO: Should use something else.
22324        return getVerticalScrollFactor();
22325    }
22326
22327    /**
22328     * Return the value specifying the text direction or policy that was set with
22329     * {@link #setTextDirection(int)}.
22330     *
22331     * @return the defined text direction. It can be one of:
22332     *
22333     * {@link #TEXT_DIRECTION_INHERIT},
22334     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22335     * {@link #TEXT_DIRECTION_ANY_RTL},
22336     * {@link #TEXT_DIRECTION_LTR},
22337     * {@link #TEXT_DIRECTION_RTL},
22338     * {@link #TEXT_DIRECTION_LOCALE},
22339     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22340     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
22341     *
22342     * @attr ref android.R.styleable#View_textDirection
22343     *
22344     * @hide
22345     */
22346    @ViewDebug.ExportedProperty(category = "text", mapping = {
22347            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
22348            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
22349            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
22350            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
22351            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
22352            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
22353            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
22354            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
22355    })
22356    public int getRawTextDirection() {
22357        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
22358    }
22359
22360    /**
22361     * Set the text direction.
22362     *
22363     * @param textDirection the direction to set. Should be one of:
22364     *
22365     * {@link #TEXT_DIRECTION_INHERIT},
22366     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22367     * {@link #TEXT_DIRECTION_ANY_RTL},
22368     * {@link #TEXT_DIRECTION_LTR},
22369     * {@link #TEXT_DIRECTION_RTL},
22370     * {@link #TEXT_DIRECTION_LOCALE}
22371     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22372     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
22373     *
22374     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
22375     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
22376     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
22377     *
22378     * @attr ref android.R.styleable#View_textDirection
22379     */
22380    public void setTextDirection(int textDirection) {
22381        if (getRawTextDirection() != textDirection) {
22382            // Reset the current text direction and the resolved one
22383            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
22384            resetResolvedTextDirection();
22385            // Set the new text direction
22386            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
22387            // Do resolution
22388            resolveTextDirection();
22389            // Notify change
22390            onRtlPropertiesChanged(getLayoutDirection());
22391            // Refresh
22392            requestLayout();
22393            invalidate(true);
22394        }
22395    }
22396
22397    /**
22398     * Return the resolved text direction.
22399     *
22400     * @return the resolved text direction. Returns one of:
22401     *
22402     * {@link #TEXT_DIRECTION_FIRST_STRONG},
22403     * {@link #TEXT_DIRECTION_ANY_RTL},
22404     * {@link #TEXT_DIRECTION_LTR},
22405     * {@link #TEXT_DIRECTION_RTL},
22406     * {@link #TEXT_DIRECTION_LOCALE},
22407     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
22408     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
22409     *
22410     * @attr ref android.R.styleable#View_textDirection
22411     */
22412    @ViewDebug.ExportedProperty(category = "text", mapping = {
22413            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
22414            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
22415            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
22416            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
22417            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
22418            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
22419            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
22420            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
22421    })
22422    public int getTextDirection() {
22423        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
22424    }
22425
22426    /**
22427     * Resolve the text direction.
22428     *
22429     * @return true if resolution has been done, false otherwise.
22430     *
22431     * @hide
22432     */
22433    public boolean resolveTextDirection() {
22434        // Reset any previous text direction resolution
22435        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
22436
22437        if (hasRtlSupport()) {
22438            // Set resolved text direction flag depending on text direction flag
22439            final int textDirection = getRawTextDirection();
22440            switch(textDirection) {
22441                case TEXT_DIRECTION_INHERIT:
22442                    if (!canResolveTextDirection()) {
22443                        // We cannot do the resolution if there is no parent, so use the default one
22444                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22445                        // Resolution will need to happen again later
22446                        return false;
22447                    }
22448
22449                    // Parent has not yet resolved, so we still return the default
22450                    try {
22451                        if (!mParent.isTextDirectionResolved()) {
22452                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22453                            // Resolution will need to happen again later
22454                            return false;
22455                        }
22456                    } catch (AbstractMethodError e) {
22457                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22458                                " does not fully implement ViewParent", e);
22459                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
22460                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22461                        return true;
22462                    }
22463
22464                    // Set current resolved direction to the same value as the parent's one
22465                    int parentResolvedDirection;
22466                    try {
22467                        parentResolvedDirection = mParent.getTextDirection();
22468                    } catch (AbstractMethodError e) {
22469                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22470                                " does not fully implement ViewParent", e);
22471                        parentResolvedDirection = TEXT_DIRECTION_LTR;
22472                    }
22473                    switch (parentResolvedDirection) {
22474                        case TEXT_DIRECTION_FIRST_STRONG:
22475                        case TEXT_DIRECTION_ANY_RTL:
22476                        case TEXT_DIRECTION_LTR:
22477                        case TEXT_DIRECTION_RTL:
22478                        case TEXT_DIRECTION_LOCALE:
22479                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
22480                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
22481                            mPrivateFlags2 |=
22482                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
22483                            break;
22484                        default:
22485                            // Default resolved direction is "first strong" heuristic
22486                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22487                    }
22488                    break;
22489                case TEXT_DIRECTION_FIRST_STRONG:
22490                case TEXT_DIRECTION_ANY_RTL:
22491                case TEXT_DIRECTION_LTR:
22492                case TEXT_DIRECTION_RTL:
22493                case TEXT_DIRECTION_LOCALE:
22494                case TEXT_DIRECTION_FIRST_STRONG_LTR:
22495                case TEXT_DIRECTION_FIRST_STRONG_RTL:
22496                    // Resolved direction is the same as text direction
22497                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
22498                    break;
22499                default:
22500                    // Default resolved direction is "first strong" heuristic
22501                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22502            }
22503        } else {
22504            // Default resolved direction is "first strong" heuristic
22505            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22506        }
22507
22508        // Set to resolved
22509        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
22510        return true;
22511    }
22512
22513    /**
22514     * Check if text direction resolution can be done.
22515     *
22516     * @return true if text direction resolution can be done otherwise return false.
22517     */
22518    public boolean canResolveTextDirection() {
22519        switch (getRawTextDirection()) {
22520            case TEXT_DIRECTION_INHERIT:
22521                if (mParent != null) {
22522                    try {
22523                        return mParent.canResolveTextDirection();
22524                    } catch (AbstractMethodError e) {
22525                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22526                                " does not fully implement ViewParent", e);
22527                    }
22528                }
22529                return false;
22530
22531            default:
22532                return true;
22533        }
22534    }
22535
22536    /**
22537     * Reset resolved text direction. Text direction will be resolved during a call to
22538     * {@link #onMeasure(int, int)}.
22539     *
22540     * @hide
22541     */
22542    public void resetResolvedTextDirection() {
22543        // Reset any previous text direction resolution
22544        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
22545        // Set to default value
22546        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
22547    }
22548
22549    /**
22550     * @return true if text direction is inherited.
22551     *
22552     * @hide
22553     */
22554    public boolean isTextDirectionInherited() {
22555        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
22556    }
22557
22558    /**
22559     * @return true if text direction is resolved.
22560     */
22561    public boolean isTextDirectionResolved() {
22562        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
22563    }
22564
22565    /**
22566     * Return the value specifying the text alignment or policy that was set with
22567     * {@link #setTextAlignment(int)}.
22568     *
22569     * @return the defined text alignment. It can be one of:
22570     *
22571     * {@link #TEXT_ALIGNMENT_INHERIT},
22572     * {@link #TEXT_ALIGNMENT_GRAVITY},
22573     * {@link #TEXT_ALIGNMENT_CENTER},
22574     * {@link #TEXT_ALIGNMENT_TEXT_START},
22575     * {@link #TEXT_ALIGNMENT_TEXT_END},
22576     * {@link #TEXT_ALIGNMENT_VIEW_START},
22577     * {@link #TEXT_ALIGNMENT_VIEW_END}
22578     *
22579     * @attr ref android.R.styleable#View_textAlignment
22580     *
22581     * @hide
22582     */
22583    @ViewDebug.ExportedProperty(category = "text", mapping = {
22584            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
22585            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
22586            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
22587            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
22588            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
22589            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
22590            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
22591    })
22592    @TextAlignment
22593    public int getRawTextAlignment() {
22594        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
22595    }
22596
22597    /**
22598     * Set the text alignment.
22599     *
22600     * @param textAlignment The text alignment to set. Should be one of
22601     *
22602     * {@link #TEXT_ALIGNMENT_INHERIT},
22603     * {@link #TEXT_ALIGNMENT_GRAVITY},
22604     * {@link #TEXT_ALIGNMENT_CENTER},
22605     * {@link #TEXT_ALIGNMENT_TEXT_START},
22606     * {@link #TEXT_ALIGNMENT_TEXT_END},
22607     * {@link #TEXT_ALIGNMENT_VIEW_START},
22608     * {@link #TEXT_ALIGNMENT_VIEW_END}
22609     *
22610     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
22611     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
22612     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
22613     *
22614     * @attr ref android.R.styleable#View_textAlignment
22615     */
22616    public void setTextAlignment(@TextAlignment int textAlignment) {
22617        if (textAlignment != getRawTextAlignment()) {
22618            // Reset the current and resolved text alignment
22619            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
22620            resetResolvedTextAlignment();
22621            // Set the new text alignment
22622            mPrivateFlags2 |=
22623                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
22624            // Do resolution
22625            resolveTextAlignment();
22626            // Notify change
22627            onRtlPropertiesChanged(getLayoutDirection());
22628            // Refresh
22629            requestLayout();
22630            invalidate(true);
22631        }
22632    }
22633
22634    /**
22635     * Return the resolved text alignment.
22636     *
22637     * @return the resolved text alignment. Returns one of:
22638     *
22639     * {@link #TEXT_ALIGNMENT_GRAVITY},
22640     * {@link #TEXT_ALIGNMENT_CENTER},
22641     * {@link #TEXT_ALIGNMENT_TEXT_START},
22642     * {@link #TEXT_ALIGNMENT_TEXT_END},
22643     * {@link #TEXT_ALIGNMENT_VIEW_START},
22644     * {@link #TEXT_ALIGNMENT_VIEW_END}
22645     *
22646     * @attr ref android.R.styleable#View_textAlignment
22647     */
22648    @ViewDebug.ExportedProperty(category = "text", mapping = {
22649            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
22650            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
22651            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
22652            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
22653            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
22654            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
22655            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
22656    })
22657    @TextAlignment
22658    public int getTextAlignment() {
22659        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
22660                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
22661    }
22662
22663    /**
22664     * Resolve the text alignment.
22665     *
22666     * @return true if resolution has been done, false otherwise.
22667     *
22668     * @hide
22669     */
22670    public boolean resolveTextAlignment() {
22671        // Reset any previous text alignment resolution
22672        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
22673
22674        if (hasRtlSupport()) {
22675            // Set resolved text alignment flag depending on text alignment flag
22676            final int textAlignment = getRawTextAlignment();
22677            switch (textAlignment) {
22678                case TEXT_ALIGNMENT_INHERIT:
22679                    // Check if we can resolve the text alignment
22680                    if (!canResolveTextAlignment()) {
22681                        // We cannot do the resolution if there is no parent so use the default
22682                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22683                        // Resolution will need to happen again later
22684                        return false;
22685                    }
22686
22687                    // Parent has not yet resolved, so we still return the default
22688                    try {
22689                        if (!mParent.isTextAlignmentResolved()) {
22690                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22691                            // Resolution will need to happen again later
22692                            return false;
22693                        }
22694                    } catch (AbstractMethodError e) {
22695                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22696                                " does not fully implement ViewParent", e);
22697                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
22698                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22699                        return true;
22700                    }
22701
22702                    int parentResolvedTextAlignment;
22703                    try {
22704                        parentResolvedTextAlignment = mParent.getTextAlignment();
22705                    } catch (AbstractMethodError e) {
22706                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22707                                " does not fully implement ViewParent", e);
22708                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
22709                    }
22710                    switch (parentResolvedTextAlignment) {
22711                        case TEXT_ALIGNMENT_GRAVITY:
22712                        case TEXT_ALIGNMENT_TEXT_START:
22713                        case TEXT_ALIGNMENT_TEXT_END:
22714                        case TEXT_ALIGNMENT_CENTER:
22715                        case TEXT_ALIGNMENT_VIEW_START:
22716                        case TEXT_ALIGNMENT_VIEW_END:
22717                            // Resolved text alignment is the same as the parent resolved
22718                            // text alignment
22719                            mPrivateFlags2 |=
22720                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
22721                            break;
22722                        default:
22723                            // Use default resolved text alignment
22724                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22725                    }
22726                    break;
22727                case TEXT_ALIGNMENT_GRAVITY:
22728                case TEXT_ALIGNMENT_TEXT_START:
22729                case TEXT_ALIGNMENT_TEXT_END:
22730                case TEXT_ALIGNMENT_CENTER:
22731                case TEXT_ALIGNMENT_VIEW_START:
22732                case TEXT_ALIGNMENT_VIEW_END:
22733                    // Resolved text alignment is the same as text alignment
22734                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
22735                    break;
22736                default:
22737                    // Use default resolved text alignment
22738                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22739            }
22740        } else {
22741            // Use default resolved text alignment
22742            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22743        }
22744
22745        // Set the resolved
22746        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
22747        return true;
22748    }
22749
22750    /**
22751     * Check if text alignment resolution can be done.
22752     *
22753     * @return true if text alignment resolution can be done otherwise return false.
22754     */
22755    public boolean canResolveTextAlignment() {
22756        switch (getRawTextAlignment()) {
22757            case TEXT_DIRECTION_INHERIT:
22758                if (mParent != null) {
22759                    try {
22760                        return mParent.canResolveTextAlignment();
22761                    } catch (AbstractMethodError e) {
22762                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
22763                                " does not fully implement ViewParent", e);
22764                    }
22765                }
22766                return false;
22767
22768            default:
22769                return true;
22770        }
22771    }
22772
22773    /**
22774     * Reset resolved text alignment. Text alignment will be resolved during a call to
22775     * {@link #onMeasure(int, int)}.
22776     *
22777     * @hide
22778     */
22779    public void resetResolvedTextAlignment() {
22780        // Reset any previous text alignment resolution
22781        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
22782        // Set to default
22783        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
22784    }
22785
22786    /**
22787     * @return true if text alignment is inherited.
22788     *
22789     * @hide
22790     */
22791    public boolean isTextAlignmentInherited() {
22792        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
22793    }
22794
22795    /**
22796     * @return true if text alignment is resolved.
22797     */
22798    public boolean isTextAlignmentResolved() {
22799        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
22800    }
22801
22802    /**
22803     * Generate a value suitable for use in {@link #setId(int)}.
22804     * This value will not collide with ID values generated at build time by aapt for R.id.
22805     *
22806     * @return a generated ID value
22807     */
22808    public static int generateViewId() {
22809        for (;;) {
22810            final int result = sNextGeneratedId.get();
22811            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
22812            int newValue = result + 1;
22813            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
22814            if (sNextGeneratedId.compareAndSet(result, newValue)) {
22815                return result;
22816            }
22817        }
22818    }
22819
22820    private static boolean isViewIdGenerated(int id) {
22821        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
22822    }
22823
22824    /**
22825     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
22826     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
22827     *                           a normal View or a ViewGroup with
22828     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
22829     * @hide
22830     */
22831    public void captureTransitioningViews(List<View> transitioningViews) {
22832        if (getVisibility() == View.VISIBLE) {
22833            transitioningViews.add(this);
22834        }
22835    }
22836
22837    /**
22838     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
22839     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
22840     * @hide
22841     */
22842    public void findNamedViews(Map<String, View> namedElements) {
22843        if (getVisibility() == VISIBLE || mGhostView != null) {
22844            String transitionName = getTransitionName();
22845            if (transitionName != null) {
22846                namedElements.put(transitionName, this);
22847            }
22848        }
22849    }
22850
22851    /**
22852     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
22853     * The default implementation does not care the location or event types, but some subclasses
22854     * may use it (such as WebViews).
22855     * @param event The MotionEvent from a mouse
22856     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
22857     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
22858     * @see PointerIcon
22859     */
22860    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
22861        final float x = event.getX(pointerIndex);
22862        final float y = event.getY(pointerIndex);
22863        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
22864            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
22865        }
22866        return mPointerIcon;
22867    }
22868
22869    /**
22870     * Set the pointer icon for the current view.
22871     * Passing {@code null} will restore the pointer icon to its default value.
22872     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
22873     */
22874    public void setPointerIcon(PointerIcon pointerIcon) {
22875        mPointerIcon = pointerIcon;
22876        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
22877            return;
22878        }
22879        try {
22880            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
22881        } catch (RemoteException e) {
22882        }
22883    }
22884
22885    /**
22886     * Gets the pointer icon for the current view.
22887     */
22888    public PointerIcon getPointerIcon() {
22889        return mPointerIcon;
22890    }
22891
22892    /**
22893     * Checks pointer capture status.
22894     *
22895     * @return true if the view has pointer capture.
22896     * @see #requestPointerCapture()
22897     * @see #hasPointerCapture()
22898     */
22899    public boolean hasPointerCapture() {
22900        final ViewRootImpl viewRootImpl = getViewRootImpl();
22901        if (viewRootImpl == null) {
22902            return false;
22903        }
22904        return viewRootImpl.hasPointerCapture();
22905    }
22906
22907    /**
22908     * Requests pointer capture mode.
22909     * <p>
22910     * When the window has pointer capture, the mouse pointer icon will disappear and will not
22911     * change its position. Further mouse will be dispatched with the source
22912     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
22913     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
22914     * (touchscreens, or stylus) will not be affected.
22915     * <p>
22916     * If the window already has pointer capture, this call does nothing.
22917     * <p>
22918     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
22919     * automatically when the window loses focus.
22920     *
22921     * @see #releasePointerCapture()
22922     * @see #hasPointerCapture()
22923     */
22924    public void requestPointerCapture() {
22925        final ViewRootImpl viewRootImpl = getViewRootImpl();
22926        if (viewRootImpl != null) {
22927            viewRootImpl.requestPointerCapture(true);
22928        }
22929    }
22930
22931
22932    /**
22933     * Releases the pointer capture.
22934     * <p>
22935     * If the window does not have pointer capture, this call will do nothing.
22936     * @see #requestPointerCapture()
22937     * @see #hasPointerCapture()
22938     */
22939    public void releasePointerCapture() {
22940        final ViewRootImpl viewRootImpl = getViewRootImpl();
22941        if (viewRootImpl != null) {
22942            viewRootImpl.requestPointerCapture(false);
22943        }
22944    }
22945
22946    /**
22947     * Called when the window has just acquired or lost pointer capture.
22948     *
22949     * @param hasCapture True if the view now has pointerCapture, false otherwise.
22950     */
22951    @CallSuper
22952    public void onPointerCaptureChange(boolean hasCapture) {
22953    }
22954
22955    /**
22956     * @see #onPointerCaptureChange
22957     */
22958    public void dispatchPointerCaptureChanged(boolean hasCapture) {
22959        onPointerCaptureChange(hasCapture);
22960    }
22961
22962    /**
22963     * Implement this method to handle captured pointer events
22964     *
22965     * @param event The captured pointer event.
22966     * @return True if the event was handled, false otherwise.
22967     * @see #requestPointerCapture()
22968     */
22969    public boolean onCapturedPointerEvent(MotionEvent event) {
22970        return false;
22971    }
22972
22973    /**
22974     * Interface definition for a callback to be invoked when a captured pointer event
22975     * is being dispatched this view. The callback will be invoked before the event is
22976     * given to the view.
22977     */
22978    public interface OnCapturedPointerListener {
22979        /**
22980         * Called when a captured pointer event is dispatched to a view.
22981         * @param view The view this event has been dispatched to.
22982         * @param event The captured event.
22983         * @return True if the listener has consumed the event, false otherwise.
22984         */
22985        boolean onCapturedPointer(View view, MotionEvent event);
22986    }
22987
22988    /**
22989     * Set a listener to receive callbacks when the pointer capture state of a view changes.
22990     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
22991     */
22992    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
22993        getListenerInfo().mOnCapturedPointerListener = l;
22994    }
22995
22996    // Properties
22997    //
22998    /**
22999     * A Property wrapper around the <code>alpha</code> functionality handled by the
23000     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
23001     */
23002    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
23003        @Override
23004        public void setValue(View object, float value) {
23005            object.setAlpha(value);
23006        }
23007
23008        @Override
23009        public Float get(View object) {
23010            return object.getAlpha();
23011        }
23012    };
23013
23014    /**
23015     * A Property wrapper around the <code>translationX</code> functionality handled by the
23016     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
23017     */
23018    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
23019        @Override
23020        public void setValue(View object, float value) {
23021            object.setTranslationX(value);
23022        }
23023
23024                @Override
23025        public Float get(View object) {
23026            return object.getTranslationX();
23027        }
23028    };
23029
23030    /**
23031     * A Property wrapper around the <code>translationY</code> functionality handled by the
23032     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
23033     */
23034    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
23035        @Override
23036        public void setValue(View object, float value) {
23037            object.setTranslationY(value);
23038        }
23039
23040        @Override
23041        public Float get(View object) {
23042            return object.getTranslationY();
23043        }
23044    };
23045
23046    /**
23047     * A Property wrapper around the <code>translationZ</code> functionality handled by the
23048     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
23049     */
23050    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
23051        @Override
23052        public void setValue(View object, float value) {
23053            object.setTranslationZ(value);
23054        }
23055
23056        @Override
23057        public Float get(View object) {
23058            return object.getTranslationZ();
23059        }
23060    };
23061
23062    /**
23063     * A Property wrapper around the <code>x</code> functionality handled by the
23064     * {@link View#setX(float)} and {@link View#getX()} methods.
23065     */
23066    public static final Property<View, Float> X = new FloatProperty<View>("x") {
23067        @Override
23068        public void setValue(View object, float value) {
23069            object.setX(value);
23070        }
23071
23072        @Override
23073        public Float get(View object) {
23074            return object.getX();
23075        }
23076    };
23077
23078    /**
23079     * A Property wrapper around the <code>y</code> functionality handled by the
23080     * {@link View#setY(float)} and {@link View#getY()} methods.
23081     */
23082    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
23083        @Override
23084        public void setValue(View object, float value) {
23085            object.setY(value);
23086        }
23087
23088        @Override
23089        public Float get(View object) {
23090            return object.getY();
23091        }
23092    };
23093
23094    /**
23095     * A Property wrapper around the <code>z</code> functionality handled by the
23096     * {@link View#setZ(float)} and {@link View#getZ()} methods.
23097     */
23098    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
23099        @Override
23100        public void setValue(View object, float value) {
23101            object.setZ(value);
23102        }
23103
23104        @Override
23105        public Float get(View object) {
23106            return object.getZ();
23107        }
23108    };
23109
23110    /**
23111     * A Property wrapper around the <code>rotation</code> functionality handled by the
23112     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
23113     */
23114    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
23115        @Override
23116        public void setValue(View object, float value) {
23117            object.setRotation(value);
23118        }
23119
23120        @Override
23121        public Float get(View object) {
23122            return object.getRotation();
23123        }
23124    };
23125
23126    /**
23127     * A Property wrapper around the <code>rotationX</code> functionality handled by the
23128     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
23129     */
23130    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
23131        @Override
23132        public void setValue(View object, float value) {
23133            object.setRotationX(value);
23134        }
23135
23136        @Override
23137        public Float get(View object) {
23138            return object.getRotationX();
23139        }
23140    };
23141
23142    /**
23143     * A Property wrapper around the <code>rotationY</code> functionality handled by the
23144     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
23145     */
23146    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
23147        @Override
23148        public void setValue(View object, float value) {
23149            object.setRotationY(value);
23150        }
23151
23152        @Override
23153        public Float get(View object) {
23154            return object.getRotationY();
23155        }
23156    };
23157
23158    /**
23159     * A Property wrapper around the <code>scaleX</code> functionality handled by the
23160     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
23161     */
23162    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
23163        @Override
23164        public void setValue(View object, float value) {
23165            object.setScaleX(value);
23166        }
23167
23168        @Override
23169        public Float get(View object) {
23170            return object.getScaleX();
23171        }
23172    };
23173
23174    /**
23175     * A Property wrapper around the <code>scaleY</code> functionality handled by the
23176     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
23177     */
23178    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
23179        @Override
23180        public void setValue(View object, float value) {
23181            object.setScaleY(value);
23182        }
23183
23184        @Override
23185        public Float get(View object) {
23186            return object.getScaleY();
23187        }
23188    };
23189
23190    /**
23191     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
23192     * Each MeasureSpec represents a requirement for either the width or the height.
23193     * A MeasureSpec is comprised of a size and a mode. There are three possible
23194     * modes:
23195     * <dl>
23196     * <dt>UNSPECIFIED</dt>
23197     * <dd>
23198     * The parent has not imposed any constraint on the child. It can be whatever size
23199     * it wants.
23200     * </dd>
23201     *
23202     * <dt>EXACTLY</dt>
23203     * <dd>
23204     * The parent has determined an exact size for the child. The child is going to be
23205     * given those bounds regardless of how big it wants to be.
23206     * </dd>
23207     *
23208     * <dt>AT_MOST</dt>
23209     * <dd>
23210     * The child can be as large as it wants up to the specified size.
23211     * </dd>
23212     * </dl>
23213     *
23214     * MeasureSpecs are implemented as ints to reduce object allocation. This class
23215     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
23216     */
23217    public static class MeasureSpec {
23218        private static final int MODE_SHIFT = 30;
23219        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
23220
23221        /** @hide */
23222        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
23223        @Retention(RetentionPolicy.SOURCE)
23224        public @interface MeasureSpecMode {}
23225
23226        /**
23227         * Measure specification mode: The parent has not imposed any constraint
23228         * on the child. It can be whatever size it wants.
23229         */
23230        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
23231
23232        /**
23233         * Measure specification mode: The parent has determined an exact size
23234         * for the child. The child is going to be given those bounds regardless
23235         * of how big it wants to be.
23236         */
23237        public static final int EXACTLY     = 1 << MODE_SHIFT;
23238
23239        /**
23240         * Measure specification mode: The child can be as large as it wants up
23241         * to the specified size.
23242         */
23243        public static final int AT_MOST     = 2 << MODE_SHIFT;
23244
23245        /**
23246         * Creates a measure specification based on the supplied size and mode.
23247         *
23248         * The mode must always be one of the following:
23249         * <ul>
23250         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
23251         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
23252         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
23253         * </ul>
23254         *
23255         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
23256         * implementation was such that the order of arguments did not matter
23257         * and overflow in either value could impact the resulting MeasureSpec.
23258         * {@link android.widget.RelativeLayout} was affected by this bug.
23259         * Apps targeting API levels greater than 17 will get the fixed, more strict
23260         * behavior.</p>
23261         *
23262         * @param size the size of the measure specification
23263         * @param mode the mode of the measure specification
23264         * @return the measure specification based on size and mode
23265         */
23266        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
23267                                          @MeasureSpecMode int mode) {
23268            if (sUseBrokenMakeMeasureSpec) {
23269                return size + mode;
23270            } else {
23271                return (size & ~MODE_MASK) | (mode & MODE_MASK);
23272            }
23273        }
23274
23275        /**
23276         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
23277         * will automatically get a size of 0. Older apps expect this.
23278         *
23279         * @hide internal use only for compatibility with system widgets and older apps
23280         */
23281        public static int makeSafeMeasureSpec(int size, int mode) {
23282            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
23283                return 0;
23284            }
23285            return makeMeasureSpec(size, mode);
23286        }
23287
23288        /**
23289         * Extracts the mode from the supplied measure specification.
23290         *
23291         * @param measureSpec the measure specification to extract the mode from
23292         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
23293         *         {@link android.view.View.MeasureSpec#AT_MOST} or
23294         *         {@link android.view.View.MeasureSpec#EXACTLY}
23295         */
23296        @MeasureSpecMode
23297        public static int getMode(int measureSpec) {
23298            //noinspection ResourceType
23299            return (measureSpec & MODE_MASK);
23300        }
23301
23302        /**
23303         * Extracts the size from the supplied measure specification.
23304         *
23305         * @param measureSpec the measure specification to extract the size from
23306         * @return the size in pixels defined in the supplied measure specification
23307         */
23308        public static int getSize(int measureSpec) {
23309            return (measureSpec & ~MODE_MASK);
23310        }
23311
23312        static int adjust(int measureSpec, int delta) {
23313            final int mode = getMode(measureSpec);
23314            int size = getSize(measureSpec);
23315            if (mode == UNSPECIFIED) {
23316                // No need to adjust size for UNSPECIFIED mode.
23317                return makeMeasureSpec(size, UNSPECIFIED);
23318            }
23319            size += delta;
23320            if (size < 0) {
23321                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
23322                        ") spec: " + toString(measureSpec) + " delta: " + delta);
23323                size = 0;
23324            }
23325            return makeMeasureSpec(size, mode);
23326        }
23327
23328        /**
23329         * Returns a String representation of the specified measure
23330         * specification.
23331         *
23332         * @param measureSpec the measure specification to convert to a String
23333         * @return a String with the following format: "MeasureSpec: MODE SIZE"
23334         */
23335        public static String toString(int measureSpec) {
23336            int mode = getMode(measureSpec);
23337            int size = getSize(measureSpec);
23338
23339            StringBuilder sb = new StringBuilder("MeasureSpec: ");
23340
23341            if (mode == UNSPECIFIED)
23342                sb.append("UNSPECIFIED ");
23343            else if (mode == EXACTLY)
23344                sb.append("EXACTLY ");
23345            else if (mode == AT_MOST)
23346                sb.append("AT_MOST ");
23347            else
23348                sb.append(mode).append(" ");
23349
23350            sb.append(size);
23351            return sb.toString();
23352        }
23353    }
23354
23355    private final class CheckForLongPress implements Runnable {
23356        private int mOriginalWindowAttachCount;
23357        private float mX;
23358        private float mY;
23359        private boolean mOriginalPressedState;
23360
23361        @Override
23362        public void run() {
23363            if ((mOriginalPressedState == isPressed()) && (mParent != null)
23364                    && mOriginalWindowAttachCount == mWindowAttachCount) {
23365                if (performLongClick(mX, mY)) {
23366                    mHasPerformedLongPress = true;
23367                }
23368            }
23369        }
23370
23371        public void setAnchor(float x, float y) {
23372            mX = x;
23373            mY = y;
23374        }
23375
23376        public void rememberWindowAttachCount() {
23377            mOriginalWindowAttachCount = mWindowAttachCount;
23378        }
23379
23380        public void rememberPressedState() {
23381            mOriginalPressedState = isPressed();
23382        }
23383    }
23384
23385    private final class CheckForTap implements Runnable {
23386        public float x;
23387        public float y;
23388
23389        @Override
23390        public void run() {
23391            mPrivateFlags &= ~PFLAG_PREPRESSED;
23392            setPressed(true, x, y);
23393            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
23394        }
23395    }
23396
23397    private final class PerformClick implements Runnable {
23398        @Override
23399        public void run() {
23400            performClick();
23401        }
23402    }
23403
23404    /**
23405     * This method returns a ViewPropertyAnimator object, which can be used to animate
23406     * specific properties on this View.
23407     *
23408     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
23409     */
23410    public ViewPropertyAnimator animate() {
23411        if (mAnimator == null) {
23412            mAnimator = new ViewPropertyAnimator(this);
23413        }
23414        return mAnimator;
23415    }
23416
23417    /**
23418     * Sets the name of the View to be used to identify Views in Transitions.
23419     * Names should be unique in the View hierarchy.
23420     *
23421     * @param transitionName The name of the View to uniquely identify it for Transitions.
23422     */
23423    public final void setTransitionName(String transitionName) {
23424        mTransitionName = transitionName;
23425    }
23426
23427    /**
23428     * Returns the name of the View to be used to identify Views in Transitions.
23429     * Names should be unique in the View hierarchy.
23430     *
23431     * <p>This returns null if the View has not been given a name.</p>
23432     *
23433     * @return The name used of the View to be used to identify Views in Transitions or null
23434     * if no name has been given.
23435     */
23436    @ViewDebug.ExportedProperty
23437    public String getTransitionName() {
23438        return mTransitionName;
23439    }
23440
23441    /**
23442     * @hide
23443     */
23444    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
23445        // Do nothing.
23446    }
23447
23448    /**
23449     * Interface definition for a callback to be invoked when a hardware key event is
23450     * dispatched to this view. The callback will be invoked before the key event is
23451     * given to the view. This is only useful for hardware keyboards; a software input
23452     * method has no obligation to trigger this listener.
23453     */
23454    public interface OnKeyListener {
23455        /**
23456         * Called when a hardware key is dispatched to a view. This allows listeners to
23457         * get a chance to respond before the target view.
23458         * <p>Key presses in software keyboards will generally NOT trigger this method,
23459         * although some may elect to do so in some situations. Do not assume a
23460         * software input method has to be key-based; even if it is, it may use key presses
23461         * in a different way than you expect, so there is no way to reliably catch soft
23462         * input key presses.
23463         *
23464         * @param v The view the key has been dispatched to.
23465         * @param keyCode The code for the physical key that was pressed
23466         * @param event The KeyEvent object containing full information about
23467         *        the event.
23468         * @return True if the listener has consumed the event, false otherwise.
23469         */
23470        boolean onKey(View v, int keyCode, KeyEvent event);
23471    }
23472
23473    /**
23474     * Interface definition for a callback to be invoked when a touch event is
23475     * dispatched to this view. The callback will be invoked before the touch
23476     * event is given to the view.
23477     */
23478    public interface OnTouchListener {
23479        /**
23480         * Called when a touch event is dispatched to a view. This allows listeners to
23481         * get a chance to respond before the target view.
23482         *
23483         * @param v The view the touch event has been dispatched to.
23484         * @param event The MotionEvent object containing full information about
23485         *        the event.
23486         * @return True if the listener has consumed the event, false otherwise.
23487         */
23488        boolean onTouch(View v, MotionEvent event);
23489    }
23490
23491    /**
23492     * Interface definition for a callback to be invoked when a hover event is
23493     * dispatched to this view. The callback will be invoked before the hover
23494     * event is given to the view.
23495     */
23496    public interface OnHoverListener {
23497        /**
23498         * Called when a hover event is dispatched to a view. This allows listeners to
23499         * get a chance to respond before the target view.
23500         *
23501         * @param v The view the hover event has been dispatched to.
23502         * @param event The MotionEvent object containing full information about
23503         *        the event.
23504         * @return True if the listener has consumed the event, false otherwise.
23505         */
23506        boolean onHover(View v, MotionEvent event);
23507    }
23508
23509    /**
23510     * Interface definition for a callback to be invoked when a generic motion event is
23511     * dispatched to this view. The callback will be invoked before the generic motion
23512     * event is given to the view.
23513     */
23514    public interface OnGenericMotionListener {
23515        /**
23516         * Called when a generic motion event is dispatched to a view. This allows listeners to
23517         * get a chance to respond before the target view.
23518         *
23519         * @param v The view the generic motion event has been dispatched to.
23520         * @param event The MotionEvent object containing full information about
23521         *        the event.
23522         * @return True if the listener has consumed the event, false otherwise.
23523         */
23524        boolean onGenericMotion(View v, MotionEvent event);
23525    }
23526
23527    /**
23528     * Interface definition for a callback to be invoked when a view has been clicked and held.
23529     */
23530    public interface OnLongClickListener {
23531        /**
23532         * Called when a view has been clicked and held.
23533         *
23534         * @param v The view that was clicked and held.
23535         *
23536         * @return true if the callback consumed the long click, false otherwise.
23537         */
23538        boolean onLongClick(View v);
23539    }
23540
23541    /**
23542     * Interface definition for a callback to be invoked when a drag is being dispatched
23543     * to this view.  The callback will be invoked before the hosting view's own
23544     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
23545     * onDrag(event) behavior, it should return 'false' from this callback.
23546     *
23547     * <div class="special reference">
23548     * <h3>Developer Guides</h3>
23549     * <p>For a guide to implementing drag and drop features, read the
23550     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
23551     * </div>
23552     */
23553    public interface OnDragListener {
23554        /**
23555         * Called when a drag event is dispatched to a view. This allows listeners
23556         * to get a chance to override base View behavior.
23557         *
23558         * @param v The View that received the drag event.
23559         * @param event The {@link android.view.DragEvent} object for the drag event.
23560         * @return {@code true} if the drag event was handled successfully, or {@code false}
23561         * if the drag event was not handled. Note that {@code false} will trigger the View
23562         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
23563         */
23564        boolean onDrag(View v, DragEvent event);
23565    }
23566
23567    /**
23568     * Interface definition for a callback to be invoked when the focus state of
23569     * a view changed.
23570     */
23571    public interface OnFocusChangeListener {
23572        /**
23573         * Called when the focus state of a view has changed.
23574         *
23575         * @param v The view whose state has changed.
23576         * @param hasFocus The new focus state of v.
23577         */
23578        void onFocusChange(View v, boolean hasFocus);
23579    }
23580
23581    /**
23582     * Interface definition for a callback to be invoked when a view is clicked.
23583     */
23584    public interface OnClickListener {
23585        /**
23586         * Called when a view has been clicked.
23587         *
23588         * @param v The view that was clicked.
23589         */
23590        void onClick(View v);
23591    }
23592
23593    /**
23594     * Interface definition for a callback to be invoked when a view is context clicked.
23595     */
23596    public interface OnContextClickListener {
23597        /**
23598         * Called when a view is context clicked.
23599         *
23600         * @param v The view that has been context clicked.
23601         * @return true if the callback consumed the context click, false otherwise.
23602         */
23603        boolean onContextClick(View v);
23604    }
23605
23606    /**
23607     * Interface definition for a callback to be invoked when the context menu
23608     * for this view is being built.
23609     */
23610    public interface OnCreateContextMenuListener {
23611        /**
23612         * Called when the context menu for this view is being built. It is not
23613         * safe to hold onto the menu after this method returns.
23614         *
23615         * @param menu The context menu that is being built
23616         * @param v The view for which the context menu is being built
23617         * @param menuInfo Extra information about the item for which the
23618         *            context menu should be shown. This information will vary
23619         *            depending on the class of v.
23620         */
23621        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
23622    }
23623
23624    /**
23625     * Interface definition for a callback to be invoked when the status bar changes
23626     * visibility.  This reports <strong>global</strong> changes to the system UI
23627     * state, not what the application is requesting.
23628     *
23629     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
23630     */
23631    public interface OnSystemUiVisibilityChangeListener {
23632        /**
23633         * Called when the status bar changes visibility because of a call to
23634         * {@link View#setSystemUiVisibility(int)}.
23635         *
23636         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
23637         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
23638         * This tells you the <strong>global</strong> state of these UI visibility
23639         * flags, not what your app is currently applying.
23640         */
23641        public void onSystemUiVisibilityChange(int visibility);
23642    }
23643
23644    /**
23645     * Interface definition for a callback to be invoked when this view is attached
23646     * or detached from its window.
23647     */
23648    public interface OnAttachStateChangeListener {
23649        /**
23650         * Called when the view is attached to a window.
23651         * @param v The view that was attached
23652         */
23653        public void onViewAttachedToWindow(View v);
23654        /**
23655         * Called when the view is detached from a window.
23656         * @param v The view that was detached
23657         */
23658        public void onViewDetachedFromWindow(View v);
23659    }
23660
23661    /**
23662     * Listener for applying window insets on a view in a custom way.
23663     *
23664     * <p>Apps may choose to implement this interface if they want to apply custom policy
23665     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
23666     * is set, its
23667     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
23668     * method will be called instead of the View's own
23669     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
23670     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
23671     * the View's normal behavior as part of its own.</p>
23672     */
23673    public interface OnApplyWindowInsetsListener {
23674        /**
23675         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
23676         * on a View, this listener method will be called instead of the view's own
23677         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
23678         *
23679         * @param v The view applying window insets
23680         * @param insets The insets to apply
23681         * @return The insets supplied, minus any insets that were consumed
23682         */
23683        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
23684    }
23685
23686    private final class UnsetPressedState implements Runnable {
23687        @Override
23688        public void run() {
23689            setPressed(false);
23690        }
23691    }
23692
23693    /**
23694     * Base class for derived classes that want to save and restore their own
23695     * state in {@link android.view.View#onSaveInstanceState()}.
23696     */
23697    public static class BaseSavedState extends AbsSavedState {
23698        String mStartActivityRequestWhoSaved;
23699
23700        /**
23701         * Constructor used when reading from a parcel. Reads the state of the superclass.
23702         *
23703         * @param source parcel to read from
23704         */
23705        public BaseSavedState(Parcel source) {
23706            this(source, null);
23707        }
23708
23709        /**
23710         * Constructor used when reading from a parcel using a given class loader.
23711         * Reads the state of the superclass.
23712         *
23713         * @param source parcel to read from
23714         * @param loader ClassLoader to use for reading
23715         */
23716        public BaseSavedState(Parcel source, ClassLoader loader) {
23717            super(source, loader);
23718            mStartActivityRequestWhoSaved = source.readString();
23719        }
23720
23721        /**
23722         * Constructor called by derived classes when creating their SavedState objects
23723         *
23724         * @param superState The state of the superclass of this view
23725         */
23726        public BaseSavedState(Parcelable superState) {
23727            super(superState);
23728        }
23729
23730        @Override
23731        public void writeToParcel(Parcel out, int flags) {
23732            super.writeToParcel(out, flags);
23733            out.writeString(mStartActivityRequestWhoSaved);
23734        }
23735
23736        public static final Parcelable.Creator<BaseSavedState> CREATOR
23737                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
23738            @Override
23739            public BaseSavedState createFromParcel(Parcel in) {
23740                return new BaseSavedState(in);
23741            }
23742
23743            @Override
23744            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
23745                return new BaseSavedState(in, loader);
23746            }
23747
23748            @Override
23749            public BaseSavedState[] newArray(int size) {
23750                return new BaseSavedState[size];
23751            }
23752        };
23753    }
23754
23755    /**
23756     * A set of information given to a view when it is attached to its parent
23757     * window.
23758     */
23759    final static class AttachInfo {
23760        interface Callbacks {
23761            void playSoundEffect(int effectId);
23762            boolean performHapticFeedback(int effectId, boolean always);
23763        }
23764
23765        /**
23766         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
23767         * to a Handler. This class contains the target (View) to invalidate and
23768         * the coordinates of the dirty rectangle.
23769         *
23770         * For performance purposes, this class also implements a pool of up to
23771         * POOL_LIMIT objects that get reused. This reduces memory allocations
23772         * whenever possible.
23773         */
23774        static class InvalidateInfo {
23775            private static final int POOL_LIMIT = 10;
23776
23777            private static final SynchronizedPool<InvalidateInfo> sPool =
23778                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
23779
23780            View target;
23781
23782            int left;
23783            int top;
23784            int right;
23785            int bottom;
23786
23787            public static InvalidateInfo obtain() {
23788                InvalidateInfo instance = sPool.acquire();
23789                return (instance != null) ? instance : new InvalidateInfo();
23790            }
23791
23792            public void recycle() {
23793                target = null;
23794                sPool.release(this);
23795            }
23796        }
23797
23798        final IWindowSession mSession;
23799
23800        final IWindow mWindow;
23801
23802        final IBinder mWindowToken;
23803
23804        Display mDisplay;
23805
23806        final Callbacks mRootCallbacks;
23807
23808        IWindowId mIWindowId;
23809        WindowId mWindowId;
23810
23811        /**
23812         * The top view of the hierarchy.
23813         */
23814        View mRootView;
23815
23816        IBinder mPanelParentWindowToken;
23817
23818        boolean mHardwareAccelerated;
23819        boolean mHardwareAccelerationRequested;
23820        ThreadedRenderer mThreadedRenderer;
23821        List<RenderNode> mPendingAnimatingRenderNodes;
23822
23823        /**
23824         * The state of the display to which the window is attached, as reported
23825         * by {@link Display#getState()}.  Note that the display state constants
23826         * declared by {@link Display} do not exactly line up with the screen state
23827         * constants declared by {@link View} (there are more display states than
23828         * screen states).
23829         */
23830        int mDisplayState = Display.STATE_UNKNOWN;
23831
23832        /**
23833         * Scale factor used by the compatibility mode
23834         */
23835        float mApplicationScale;
23836
23837        /**
23838         * Indicates whether the application is in compatibility mode
23839         */
23840        boolean mScalingRequired;
23841
23842        /**
23843         * Left position of this view's window
23844         */
23845        int mWindowLeft;
23846
23847        /**
23848         * Top position of this view's window
23849         */
23850        int mWindowTop;
23851
23852        /**
23853         * Indicates whether views need to use 32-bit drawing caches
23854         */
23855        boolean mUse32BitDrawingCache;
23856
23857        /**
23858         * For windows that are full-screen but using insets to layout inside
23859         * of the screen areas, these are the current insets to appear inside
23860         * the overscan area of the display.
23861         */
23862        final Rect mOverscanInsets = new Rect();
23863
23864        /**
23865         * For windows that are full-screen but using insets to layout inside
23866         * of the screen decorations, these are the current insets for the
23867         * content of the window.
23868         */
23869        final Rect mContentInsets = new Rect();
23870
23871        /**
23872         * For windows that are full-screen but using insets to layout inside
23873         * of the screen decorations, these are the current insets for the
23874         * actual visible parts of the window.
23875         */
23876        final Rect mVisibleInsets = new Rect();
23877
23878        /**
23879         * For windows that are full-screen but using insets to layout inside
23880         * of the screen decorations, these are the current insets for the
23881         * stable system windows.
23882         */
23883        final Rect mStableInsets = new Rect();
23884
23885        /**
23886         * For windows that include areas that are not covered by real surface these are the outsets
23887         * for real surface.
23888         */
23889        final Rect mOutsets = new Rect();
23890
23891        /**
23892         * In multi-window we force show the navigation bar. Because we don't want that the surface
23893         * size changes in this mode, we instead have a flag whether the navigation bar size should
23894         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
23895         */
23896        boolean mAlwaysConsumeNavBar;
23897
23898        /**
23899         * The internal insets given by this window.  This value is
23900         * supplied by the client (through
23901         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
23902         * be given to the window manager when changed to be used in laying
23903         * out windows behind it.
23904         */
23905        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
23906                = new ViewTreeObserver.InternalInsetsInfo();
23907
23908        /**
23909         * Set to true when mGivenInternalInsets is non-empty.
23910         */
23911        boolean mHasNonEmptyGivenInternalInsets;
23912
23913        /**
23914         * All views in the window's hierarchy that serve as scroll containers,
23915         * used to determine if the window can be resized or must be panned
23916         * to adjust for a soft input area.
23917         */
23918        final ArrayList<View> mScrollContainers = new ArrayList<View>();
23919
23920        final KeyEvent.DispatcherState mKeyDispatchState
23921                = new KeyEvent.DispatcherState();
23922
23923        /**
23924         * Indicates whether the view's window currently has the focus.
23925         */
23926        boolean mHasWindowFocus;
23927
23928        /**
23929         * The current visibility of the window.
23930         */
23931        int mWindowVisibility;
23932
23933        /**
23934         * Indicates the time at which drawing started to occur.
23935         */
23936        long mDrawingTime;
23937
23938        /**
23939         * Indicates whether or not ignoring the DIRTY_MASK flags.
23940         */
23941        boolean mIgnoreDirtyState;
23942
23943        /**
23944         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
23945         * to avoid clearing that flag prematurely.
23946         */
23947        boolean mSetIgnoreDirtyState = false;
23948
23949        /**
23950         * Indicates whether the view's window is currently in touch mode.
23951         */
23952        boolean mInTouchMode;
23953
23954        /**
23955         * Indicates whether the view has requested unbuffered input dispatching for the current
23956         * event stream.
23957         */
23958        boolean mUnbufferedDispatchRequested;
23959
23960        /**
23961         * Indicates that ViewAncestor should trigger a global layout change
23962         * the next time it performs a traversal
23963         */
23964        boolean mRecomputeGlobalAttributes;
23965
23966        /**
23967         * Always report new attributes at next traversal.
23968         */
23969        boolean mForceReportNewAttributes;
23970
23971        /**
23972         * Set during a traveral if any views want to keep the screen on.
23973         */
23974        boolean mKeepScreenOn;
23975
23976        /**
23977         * Set during a traveral if the light center needs to be updated.
23978         */
23979        boolean mNeedsUpdateLightCenter;
23980
23981        /**
23982         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
23983         */
23984        int mSystemUiVisibility;
23985
23986        /**
23987         * Hack to force certain system UI visibility flags to be cleared.
23988         */
23989        int mDisabledSystemUiVisibility;
23990
23991        /**
23992         * Last global system UI visibility reported by the window manager.
23993         */
23994        int mGlobalSystemUiVisibility = -1;
23995
23996        /**
23997         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
23998         * attached.
23999         */
24000        boolean mHasSystemUiListeners;
24001
24002        /**
24003         * Set if the window has requested to extend into the overscan region
24004         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
24005         */
24006        boolean mOverscanRequested;
24007
24008        /**
24009         * Set if the visibility of any views has changed.
24010         */
24011        boolean mViewVisibilityChanged;
24012
24013        /**
24014         * Set to true if a view has been scrolled.
24015         */
24016        boolean mViewScrollChanged;
24017
24018        /**
24019         * Set to true if high contrast mode enabled
24020         */
24021        boolean mHighContrastText;
24022
24023        /**
24024         * Set to true if a pointer event is currently being handled.
24025         */
24026        boolean mHandlingPointerEvent;
24027
24028        /**
24029         * Global to the view hierarchy used as a temporary for dealing with
24030         * x/y points in the transparent region computations.
24031         */
24032        final int[] mTransparentLocation = new int[2];
24033
24034        /**
24035         * Global to the view hierarchy used as a temporary for dealing with
24036         * x/y points in the ViewGroup.invalidateChild implementation.
24037         */
24038        final int[] mInvalidateChildLocation = new int[2];
24039
24040        /**
24041         * Global to the view hierarchy used as a temporary for dealing with
24042         * computing absolute on-screen location.
24043         */
24044        final int[] mTmpLocation = new int[2];
24045
24046        /**
24047         * Global to the view hierarchy used as a temporary for dealing with
24048         * x/y location when view is transformed.
24049         */
24050        final float[] mTmpTransformLocation = new float[2];
24051
24052        /**
24053         * The view tree observer used to dispatch global events like
24054         * layout, pre-draw, touch mode change, etc.
24055         */
24056        final ViewTreeObserver mTreeObserver;
24057
24058        /**
24059         * A Canvas used by the view hierarchy to perform bitmap caching.
24060         */
24061        Canvas mCanvas;
24062
24063        /**
24064         * The view root impl.
24065         */
24066        final ViewRootImpl mViewRootImpl;
24067
24068        /**
24069         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
24070         * handler can be used to pump events in the UI events queue.
24071         */
24072        final Handler mHandler;
24073
24074        /**
24075         * Temporary for use in computing invalidate rectangles while
24076         * calling up the hierarchy.
24077         */
24078        final Rect mTmpInvalRect = new Rect();
24079
24080        /**
24081         * Temporary for use in computing hit areas with transformed views
24082         */
24083        final RectF mTmpTransformRect = new RectF();
24084
24085        /**
24086         * Temporary for use in computing hit areas with transformed views
24087         */
24088        final RectF mTmpTransformRect1 = new RectF();
24089
24090        /**
24091         * Temporary list of rectanges.
24092         */
24093        final List<RectF> mTmpRectList = new ArrayList<>();
24094
24095        /**
24096         * Temporary for use in transforming invalidation rect
24097         */
24098        final Matrix mTmpMatrix = new Matrix();
24099
24100        /**
24101         * Temporary for use in transforming invalidation rect
24102         */
24103        final Transformation mTmpTransformation = new Transformation();
24104
24105        /**
24106         * Temporary for use in querying outlines from OutlineProviders
24107         */
24108        final Outline mTmpOutline = new Outline();
24109
24110        /**
24111         * Temporary list for use in collecting focusable descendents of a view.
24112         */
24113        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
24114
24115        /**
24116         * The id of the window for accessibility purposes.
24117         */
24118        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
24119
24120        /**
24121         * Flags related to accessibility processing.
24122         *
24123         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
24124         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
24125         */
24126        int mAccessibilityFetchFlags;
24127
24128        /**
24129         * The drawable for highlighting accessibility focus.
24130         */
24131        Drawable mAccessibilityFocusDrawable;
24132
24133        /**
24134         * Show where the margins, bounds and layout bounds are for each view.
24135         */
24136        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
24137
24138        /**
24139         * Point used to compute visible regions.
24140         */
24141        final Point mPoint = new Point();
24142
24143        /**
24144         * Used to track which View originated a requestLayout() call, used when
24145         * requestLayout() is called during layout.
24146         */
24147        View mViewRequestingLayout;
24148
24149        /**
24150         * Used to track views that need (at least) a partial relayout at their current size
24151         * during the next traversal.
24152         */
24153        List<View> mPartialLayoutViews = new ArrayList<>();
24154
24155        /**
24156         * Swapped with mPartialLayoutViews during layout to avoid concurrent
24157         * modification. Lazily assigned during ViewRootImpl layout.
24158         */
24159        List<View> mEmptyPartialLayoutViews;
24160
24161        /**
24162         * Used to track the identity of the current drag operation.
24163         */
24164        IBinder mDragToken;
24165
24166        /**
24167         * The drag shadow surface for the current drag operation.
24168         */
24169        public Surface mDragSurface;
24170
24171
24172        /**
24173         * The view that currently has a tooltip displayed.
24174         */
24175        View mTooltipHost;
24176
24177        /**
24178         * Creates a new set of attachment information with the specified
24179         * events handler and thread.
24180         *
24181         * @param handler the events handler the view must use
24182         */
24183        AttachInfo(IWindowSession session, IWindow window, Display display,
24184                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
24185                Context context) {
24186            mSession = session;
24187            mWindow = window;
24188            mWindowToken = window.asBinder();
24189            mDisplay = display;
24190            mViewRootImpl = viewRootImpl;
24191            mHandler = handler;
24192            mRootCallbacks = effectPlayer;
24193            mTreeObserver = new ViewTreeObserver(context);
24194        }
24195    }
24196
24197    /**
24198     * <p>ScrollabilityCache holds various fields used by a View when scrolling
24199     * is supported. This avoids keeping too many unused fields in most
24200     * instances of View.</p>
24201     */
24202    private static class ScrollabilityCache implements Runnable {
24203
24204        /**
24205         * Scrollbars are not visible
24206         */
24207        public static final int OFF = 0;
24208
24209        /**
24210         * Scrollbars are visible
24211         */
24212        public static final int ON = 1;
24213
24214        /**
24215         * Scrollbars are fading away
24216         */
24217        public static final int FADING = 2;
24218
24219        public boolean fadeScrollBars;
24220
24221        public int fadingEdgeLength;
24222        public int scrollBarDefaultDelayBeforeFade;
24223        public int scrollBarFadeDuration;
24224
24225        public int scrollBarSize;
24226        public int scrollBarMinTouchTarget;
24227        public ScrollBarDrawable scrollBar;
24228        public float[] interpolatorValues;
24229        public View host;
24230
24231        public final Paint paint;
24232        public final Matrix matrix;
24233        public Shader shader;
24234
24235        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
24236
24237        private static final float[] OPAQUE = { 255 };
24238        private static final float[] TRANSPARENT = { 0.0f };
24239
24240        /**
24241         * When fading should start. This time moves into the future every time
24242         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
24243         */
24244        public long fadeStartTime;
24245
24246
24247        /**
24248         * The current state of the scrollbars: ON, OFF, or FADING
24249         */
24250        public int state = OFF;
24251
24252        private int mLastColor;
24253
24254        public final Rect mScrollBarBounds = new Rect();
24255        public final Rect mScrollBarTouchBounds = new Rect();
24256
24257        public static final int NOT_DRAGGING = 0;
24258        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
24259        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
24260        public int mScrollBarDraggingState = NOT_DRAGGING;
24261
24262        public float mScrollBarDraggingPos = 0;
24263
24264        public ScrollabilityCache(ViewConfiguration configuration, View host) {
24265            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
24266            scrollBarSize = configuration.getScaledScrollBarSize();
24267            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
24268            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
24269            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
24270
24271            paint = new Paint();
24272            matrix = new Matrix();
24273            // use use a height of 1, and then wack the matrix each time we
24274            // actually use it.
24275            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
24276            paint.setShader(shader);
24277            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
24278
24279            this.host = host;
24280        }
24281
24282        public void setFadeColor(int color) {
24283            if (color != mLastColor) {
24284                mLastColor = color;
24285
24286                if (color != 0) {
24287                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
24288                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
24289                    paint.setShader(shader);
24290                    // Restore the default transfer mode (src_over)
24291                    paint.setXfermode(null);
24292                } else {
24293                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
24294                    paint.setShader(shader);
24295                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
24296                }
24297            }
24298        }
24299
24300        public void run() {
24301            long now = AnimationUtils.currentAnimationTimeMillis();
24302            if (now >= fadeStartTime) {
24303
24304                // the animation fades the scrollbars out by changing
24305                // the opacity (alpha) from fully opaque to fully
24306                // transparent
24307                int nextFrame = (int) now;
24308                int framesCount = 0;
24309
24310                Interpolator interpolator = scrollBarInterpolator;
24311
24312                // Start opaque
24313                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
24314
24315                // End transparent
24316                nextFrame += scrollBarFadeDuration;
24317                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
24318
24319                state = FADING;
24320
24321                // Kick off the fade animation
24322                host.invalidate(true);
24323            }
24324        }
24325    }
24326
24327    /**
24328     * Resuable callback for sending
24329     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
24330     */
24331    private class SendViewScrolledAccessibilityEvent implements Runnable {
24332        public volatile boolean mIsPending;
24333
24334        public void run() {
24335            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
24336            mIsPending = false;
24337        }
24338    }
24339
24340    /**
24341     * <p>
24342     * This class represents a delegate that can be registered in a {@link View}
24343     * to enhance accessibility support via composition rather via inheritance.
24344     * It is specifically targeted to widget developers that extend basic View
24345     * classes i.e. classes in package android.view, that would like their
24346     * applications to be backwards compatible.
24347     * </p>
24348     * <div class="special reference">
24349     * <h3>Developer Guides</h3>
24350     * <p>For more information about making applications accessible, read the
24351     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
24352     * developer guide.</p>
24353     * </div>
24354     * <p>
24355     * A scenario in which a developer would like to use an accessibility delegate
24356     * is overriding a method introduced in a later API version than the minimal API
24357     * version supported by the application. For example, the method
24358     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
24359     * in API version 4 when the accessibility APIs were first introduced. If a
24360     * developer would like his application to run on API version 4 devices (assuming
24361     * all other APIs used by the application are version 4 or lower) and take advantage
24362     * of this method, instead of overriding the method which would break the application's
24363     * backwards compatibility, he can override the corresponding method in this
24364     * delegate and register the delegate in the target View if the API version of
24365     * the system is high enough, i.e. the API version is the same as or higher than the API
24366     * version that introduced
24367     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
24368     * </p>
24369     * <p>
24370     * Here is an example implementation:
24371     * </p>
24372     * <code><pre><p>
24373     * if (Build.VERSION.SDK_INT >= 14) {
24374     *     // If the API version is equal of higher than the version in
24375     *     // which onInitializeAccessibilityNodeInfo was introduced we
24376     *     // register a delegate with a customized implementation.
24377     *     View view = findViewById(R.id.view_id);
24378     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
24379     *         public void onInitializeAccessibilityNodeInfo(View host,
24380     *                 AccessibilityNodeInfo info) {
24381     *             // Let the default implementation populate the info.
24382     *             super.onInitializeAccessibilityNodeInfo(host, info);
24383     *             // Set some other information.
24384     *             info.setEnabled(host.isEnabled());
24385     *         }
24386     *     });
24387     * }
24388     * </code></pre></p>
24389     * <p>
24390     * This delegate contains methods that correspond to the accessibility methods
24391     * in View. If a delegate has been specified the implementation in View hands
24392     * off handling to the corresponding method in this delegate. The default
24393     * implementation the delegate methods behaves exactly as the corresponding
24394     * method in View for the case of no accessibility delegate been set. Hence,
24395     * to customize the behavior of a View method, clients can override only the
24396     * corresponding delegate method without altering the behavior of the rest
24397     * accessibility related methods of the host view.
24398     * </p>
24399     * <p>
24400     * <strong>Note:</strong> On platform versions prior to
24401     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
24402     * views in the {@code android.widget.*} package are called <i>before</i>
24403     * host methods. This prevents certain properties such as class name from
24404     * being modified by overriding
24405     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
24406     * as any changes will be overwritten by the host class.
24407     * <p>
24408     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
24409     * methods are called <i>after</i> host methods, which all properties to be
24410     * modified without being overwritten by the host class.
24411     */
24412    public static class AccessibilityDelegate {
24413
24414        /**
24415         * Sends an accessibility event of the given type. If accessibility is not
24416         * enabled this method has no effect.
24417         * <p>
24418         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
24419         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
24420         * been set.
24421         * </p>
24422         *
24423         * @param host The View hosting the delegate.
24424         * @param eventType The type of the event to send.
24425         *
24426         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
24427         */
24428        public void sendAccessibilityEvent(View host, int eventType) {
24429            host.sendAccessibilityEventInternal(eventType);
24430        }
24431
24432        /**
24433         * Performs the specified accessibility action on the view. For
24434         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
24435         * <p>
24436         * The default implementation behaves as
24437         * {@link View#performAccessibilityAction(int, Bundle)
24438         *  View#performAccessibilityAction(int, Bundle)} for the case of
24439         *  no accessibility delegate been set.
24440         * </p>
24441         *
24442         * @param action The action to perform.
24443         * @return Whether the action was performed.
24444         *
24445         * @see View#performAccessibilityAction(int, Bundle)
24446         *      View#performAccessibilityAction(int, Bundle)
24447         */
24448        public boolean performAccessibilityAction(View host, int action, Bundle args) {
24449            return host.performAccessibilityActionInternal(action, args);
24450        }
24451
24452        /**
24453         * Sends an accessibility event. This method behaves exactly as
24454         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
24455         * empty {@link AccessibilityEvent} and does not perform a check whether
24456         * accessibility is enabled.
24457         * <p>
24458         * The default implementation behaves as
24459         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
24460         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
24461         * the case of no accessibility delegate been set.
24462         * </p>
24463         *
24464         * @param host The View hosting the delegate.
24465         * @param event The event to send.
24466         *
24467         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
24468         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
24469         */
24470        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
24471            host.sendAccessibilityEventUncheckedInternal(event);
24472        }
24473
24474        /**
24475         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
24476         * to its children for adding their text content to the event.
24477         * <p>
24478         * The default implementation behaves as
24479         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
24480         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
24481         * the case of no accessibility delegate been set.
24482         * </p>
24483         *
24484         * @param host The View hosting the delegate.
24485         * @param event The event.
24486         * @return True if the event population was completed.
24487         *
24488         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
24489         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
24490         */
24491        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
24492            return host.dispatchPopulateAccessibilityEventInternal(event);
24493        }
24494
24495        /**
24496         * Gives a chance to the host View to populate the accessibility event with its
24497         * text content.
24498         * <p>
24499         * The default implementation behaves as
24500         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
24501         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
24502         * the case of no accessibility delegate been set.
24503         * </p>
24504         *
24505         * @param host The View hosting the delegate.
24506         * @param event The accessibility event which to populate.
24507         *
24508         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
24509         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
24510         */
24511        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
24512            host.onPopulateAccessibilityEventInternal(event);
24513        }
24514
24515        /**
24516         * Initializes an {@link AccessibilityEvent} with information about the
24517         * the host View which is the event source.
24518         * <p>
24519         * The default implementation behaves as
24520         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
24521         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
24522         * the case of no accessibility delegate been set.
24523         * </p>
24524         *
24525         * @param host The View hosting the delegate.
24526         * @param event The event to initialize.
24527         *
24528         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
24529         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
24530         */
24531        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
24532            host.onInitializeAccessibilityEventInternal(event);
24533        }
24534
24535        /**
24536         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
24537         * <p>
24538         * The default implementation behaves as
24539         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24540         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
24541         * the case of no accessibility delegate been set.
24542         * </p>
24543         *
24544         * @param host The View hosting the delegate.
24545         * @param info The instance to initialize.
24546         *
24547         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24548         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
24549         */
24550        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
24551            host.onInitializeAccessibilityNodeInfoInternal(info);
24552        }
24553
24554        /**
24555         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
24556         * additional data.
24557         * <p>
24558         * This method only needs to be implemented if the View offers to provide additional data.
24559         * </p>
24560         * <p>
24561         * The default implementation behaves as
24562         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, int) for
24563         * the case where no accessibility delegate is set.
24564         * </p>
24565         *
24566         * @param host The View hosting the delegate. Never {@code null}.
24567         * @param info The info to which to add the extra data. Never {@code null}.
24568         * @param extraDataKey A key specifying the type of extra data to add to the info. The
24569         *                     extra data should be added to the {@link Bundle} returned by
24570         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
24571         *                     {@code null}.
24572         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
24573         *                  May be {@code null} if the if the service provided no arguments.
24574         *
24575         * @see AccessibilityNodeInfo#setExtraAvailableData
24576         */
24577        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
24578                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
24579                @Nullable Bundle arguments) {
24580            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
24581        }
24582
24583        /**
24584         * Called when a child of the host View has requested sending an
24585         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
24586         * to augment the event.
24587         * <p>
24588         * The default implementation behaves as
24589         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24590         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
24591         * the case of no accessibility delegate been set.
24592         * </p>
24593         *
24594         * @param host The View hosting the delegate.
24595         * @param child The child which requests sending the event.
24596         * @param event The event to be sent.
24597         * @return True if the event should be sent
24598         *
24599         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24600         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
24601         */
24602        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
24603                AccessibilityEvent event) {
24604            return host.onRequestSendAccessibilityEventInternal(child, event);
24605        }
24606
24607        /**
24608         * Gets the provider for managing a virtual view hierarchy rooted at this View
24609         * and reported to {@link android.accessibilityservice.AccessibilityService}s
24610         * that explore the window content.
24611         * <p>
24612         * The default implementation behaves as
24613         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
24614         * the case of no accessibility delegate been set.
24615         * </p>
24616         *
24617         * @return The provider.
24618         *
24619         * @see AccessibilityNodeProvider
24620         */
24621        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
24622            return null;
24623        }
24624
24625        /**
24626         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
24627         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
24628         * This method is responsible for obtaining an accessibility node info from a
24629         * pool of reusable instances and calling
24630         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
24631         * view to initialize the former.
24632         * <p>
24633         * <strong>Note:</strong> The client is responsible for recycling the obtained
24634         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
24635         * creation.
24636         * </p>
24637         * <p>
24638         * The default implementation behaves as
24639         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
24640         * the case of no accessibility delegate been set.
24641         * </p>
24642         * @return A populated {@link AccessibilityNodeInfo}.
24643         *
24644         * @see AccessibilityNodeInfo
24645         *
24646         * @hide
24647         */
24648        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
24649            return host.createAccessibilityNodeInfoInternal();
24650        }
24651    }
24652
24653    private static class MatchIdPredicate implements Predicate<View> {
24654        public int mId;
24655
24656        @Override
24657        public boolean test(View view) {
24658            return (view.mID == mId);
24659        }
24660    }
24661
24662    private static class MatchLabelForPredicate implements Predicate<View> {
24663        private int mLabeledId;
24664
24665        @Override
24666        public boolean test(View view) {
24667            return (view.mLabelForId == mLabeledId);
24668        }
24669    }
24670
24671    private class SendViewStateChangedAccessibilityEvent implements Runnable {
24672        private int mChangeTypes = 0;
24673        private boolean mPosted;
24674        private boolean mPostedWithDelay;
24675        private long mLastEventTimeMillis;
24676
24677        @Override
24678        public void run() {
24679            mPosted = false;
24680            mPostedWithDelay = false;
24681            mLastEventTimeMillis = SystemClock.uptimeMillis();
24682            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
24683                final AccessibilityEvent event = AccessibilityEvent.obtain();
24684                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
24685                event.setContentChangeTypes(mChangeTypes);
24686                sendAccessibilityEventUnchecked(event);
24687            }
24688            mChangeTypes = 0;
24689        }
24690
24691        public void runOrPost(int changeType) {
24692            mChangeTypes |= changeType;
24693
24694            // If this is a live region or the child of a live region, collect
24695            // all events from this frame and send them on the next frame.
24696            if (inLiveRegion()) {
24697                // If we're already posted with a delay, remove that.
24698                if (mPostedWithDelay) {
24699                    removeCallbacks(this);
24700                    mPostedWithDelay = false;
24701                }
24702                // Only post if we're not already posted.
24703                if (!mPosted) {
24704                    post(this);
24705                    mPosted = true;
24706                }
24707                return;
24708            }
24709
24710            if (mPosted) {
24711                return;
24712            }
24713
24714            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
24715            final long minEventIntevalMillis =
24716                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
24717            if (timeSinceLastMillis >= minEventIntevalMillis) {
24718                removeCallbacks(this);
24719                run();
24720            } else {
24721                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
24722                mPostedWithDelay = true;
24723            }
24724        }
24725    }
24726
24727    private boolean inLiveRegion() {
24728        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
24729            return true;
24730        }
24731
24732        ViewParent parent = getParent();
24733        while (parent instanceof View) {
24734            if (((View) parent).getAccessibilityLiveRegion()
24735                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
24736                return true;
24737            }
24738            parent = parent.getParent();
24739        }
24740
24741        return false;
24742    }
24743
24744    /**
24745     * Dump all private flags in readable format, useful for documentation and
24746     * sanity checking.
24747     */
24748    private static void dumpFlags() {
24749        final HashMap<String, String> found = Maps.newHashMap();
24750        try {
24751            for (Field field : View.class.getDeclaredFields()) {
24752                final int modifiers = field.getModifiers();
24753                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
24754                    if (field.getType().equals(int.class)) {
24755                        final int value = field.getInt(null);
24756                        dumpFlag(found, field.getName(), value);
24757                    } else if (field.getType().equals(int[].class)) {
24758                        final int[] values = (int[]) field.get(null);
24759                        for (int i = 0; i < values.length; i++) {
24760                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
24761                        }
24762                    }
24763                }
24764            }
24765        } catch (IllegalAccessException e) {
24766            throw new RuntimeException(e);
24767        }
24768
24769        final ArrayList<String> keys = Lists.newArrayList();
24770        keys.addAll(found.keySet());
24771        Collections.sort(keys);
24772        for (String key : keys) {
24773            Log.d(VIEW_LOG_TAG, found.get(key));
24774        }
24775    }
24776
24777    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
24778        // Sort flags by prefix, then by bits, always keeping unique keys
24779        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
24780        final int prefix = name.indexOf('_');
24781        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
24782        final String output = bits + " " + name;
24783        found.put(key, output);
24784    }
24785
24786    /** {@hide} */
24787    public void encode(@NonNull ViewHierarchyEncoder stream) {
24788        stream.beginObject(this);
24789        encodeProperties(stream);
24790        stream.endObject();
24791    }
24792
24793    /** {@hide} */
24794    @CallSuper
24795    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
24796        Object resolveId = ViewDebug.resolveId(getContext(), mID);
24797        if (resolveId instanceof String) {
24798            stream.addProperty("id", (String) resolveId);
24799        } else {
24800            stream.addProperty("id", mID);
24801        }
24802
24803        stream.addProperty("misc:transformation.alpha",
24804                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
24805        stream.addProperty("misc:transitionName", getTransitionName());
24806
24807        // layout
24808        stream.addProperty("layout:left", mLeft);
24809        stream.addProperty("layout:right", mRight);
24810        stream.addProperty("layout:top", mTop);
24811        stream.addProperty("layout:bottom", mBottom);
24812        stream.addProperty("layout:width", getWidth());
24813        stream.addProperty("layout:height", getHeight());
24814        stream.addProperty("layout:layoutDirection", getLayoutDirection());
24815        stream.addProperty("layout:layoutRtl", isLayoutRtl());
24816        stream.addProperty("layout:hasTransientState", hasTransientState());
24817        stream.addProperty("layout:baseline", getBaseline());
24818
24819        // layout params
24820        ViewGroup.LayoutParams layoutParams = getLayoutParams();
24821        if (layoutParams != null) {
24822            stream.addPropertyKey("layoutParams");
24823            layoutParams.encode(stream);
24824        }
24825
24826        // scrolling
24827        stream.addProperty("scrolling:scrollX", mScrollX);
24828        stream.addProperty("scrolling:scrollY", mScrollY);
24829
24830        // padding
24831        stream.addProperty("padding:paddingLeft", mPaddingLeft);
24832        stream.addProperty("padding:paddingRight", mPaddingRight);
24833        stream.addProperty("padding:paddingTop", mPaddingTop);
24834        stream.addProperty("padding:paddingBottom", mPaddingBottom);
24835        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
24836        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
24837        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
24838        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
24839        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
24840
24841        // measurement
24842        stream.addProperty("measurement:minHeight", mMinHeight);
24843        stream.addProperty("measurement:minWidth", mMinWidth);
24844        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
24845        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
24846
24847        // drawing
24848        stream.addProperty("drawing:elevation", getElevation());
24849        stream.addProperty("drawing:translationX", getTranslationX());
24850        stream.addProperty("drawing:translationY", getTranslationY());
24851        stream.addProperty("drawing:translationZ", getTranslationZ());
24852        stream.addProperty("drawing:rotation", getRotation());
24853        stream.addProperty("drawing:rotationX", getRotationX());
24854        stream.addProperty("drawing:rotationY", getRotationY());
24855        stream.addProperty("drawing:scaleX", getScaleX());
24856        stream.addProperty("drawing:scaleY", getScaleY());
24857        stream.addProperty("drawing:pivotX", getPivotX());
24858        stream.addProperty("drawing:pivotY", getPivotY());
24859        stream.addProperty("drawing:opaque", isOpaque());
24860        stream.addProperty("drawing:alpha", getAlpha());
24861        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
24862        stream.addProperty("drawing:shadow", hasShadow());
24863        stream.addProperty("drawing:solidColor", getSolidColor());
24864        stream.addProperty("drawing:layerType", mLayerType);
24865        stream.addProperty("drawing:willNotDraw", willNotDraw());
24866        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
24867        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
24868        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
24869        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
24870
24871        // focus
24872        stream.addProperty("focus:hasFocus", hasFocus());
24873        stream.addProperty("focus:isFocused", isFocused());
24874        stream.addProperty("focus:isFocusable", isFocusable());
24875        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
24876
24877        stream.addProperty("misc:clickable", isClickable());
24878        stream.addProperty("misc:pressed", isPressed());
24879        stream.addProperty("misc:selected", isSelected());
24880        stream.addProperty("misc:touchMode", isInTouchMode());
24881        stream.addProperty("misc:hovered", isHovered());
24882        stream.addProperty("misc:activated", isActivated());
24883
24884        stream.addProperty("misc:visibility", getVisibility());
24885        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
24886        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
24887
24888        stream.addProperty("misc:enabled", isEnabled());
24889        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
24890        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
24891
24892        // theme attributes
24893        Resources.Theme theme = getContext().getTheme();
24894        if (theme != null) {
24895            stream.addPropertyKey("theme");
24896            theme.encode(stream);
24897        }
24898
24899        // view attribute information
24900        int n = mAttributes != null ? mAttributes.length : 0;
24901        stream.addProperty("meta:__attrCount__", n/2);
24902        for (int i = 0; i < n; i += 2) {
24903            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
24904        }
24905
24906        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
24907
24908        // text
24909        stream.addProperty("text:textDirection", getTextDirection());
24910        stream.addProperty("text:textAlignment", getTextAlignment());
24911
24912        // accessibility
24913        CharSequence contentDescription = getContentDescription();
24914        stream.addProperty("accessibility:contentDescription",
24915                contentDescription == null ? "" : contentDescription.toString());
24916        stream.addProperty("accessibility:labelFor", getLabelFor());
24917        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
24918    }
24919
24920    /**
24921     * Determine if this view is rendered on a round wearable device and is the main view
24922     * on the screen.
24923     */
24924    boolean shouldDrawRoundScrollbar() {
24925        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
24926            return false;
24927        }
24928
24929        final View rootView = getRootView();
24930        final WindowInsets insets = getRootWindowInsets();
24931
24932        int height = getHeight();
24933        int width = getWidth();
24934        int displayHeight = rootView.getHeight();
24935        int displayWidth = rootView.getWidth();
24936
24937        if (height != displayHeight || width != displayWidth) {
24938            return false;
24939        }
24940
24941        getLocationInWindow(mAttachInfo.mTmpLocation);
24942        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
24943                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
24944    }
24945
24946    /**
24947     * Sets the tooltip text which will be displayed in a small popup next to the view.
24948     * <p>
24949     * The tooltip will be displayed:
24950     * <ul>
24951     * <li>On long click, unless is not handled otherwise (by OnLongClickListener or a context
24952     * menu). </li>
24953     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
24954     * </ul>
24955     * <p>
24956     * <strong>Note:</strong> Do not override this method, as it will have no
24957     * effect on the text displayed in the tooltip.
24958     *
24959     * @param tooltipText the tooltip text, or null if no tooltip is required
24960     * @see #getTooltipText()
24961     * @attr ref android.R.styleable#View_tooltipText
24962     */
24963    public void setTooltipText(@Nullable CharSequence tooltipText) {
24964        if (TextUtils.isEmpty(tooltipText)) {
24965            setFlags(0, TOOLTIP);
24966            hideTooltip();
24967            mTooltipInfo = null;
24968        } else {
24969            setFlags(TOOLTIP, TOOLTIP);
24970            if (mTooltipInfo == null) {
24971                mTooltipInfo = new TooltipInfo();
24972                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
24973                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
24974            }
24975            mTooltipInfo.mTooltipText = tooltipText;
24976            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
24977                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
24978            }
24979        }
24980    }
24981
24982    /**
24983     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
24984     */
24985    public void setTooltip(@Nullable CharSequence tooltipText) {
24986        setTooltipText(tooltipText);
24987    }
24988
24989    /**
24990     * Returns the view's tooltip text.
24991     *
24992     * <strong>Note:</strong> Do not override this method, as it will have no
24993     * effect on the text displayed in the tooltip. You must call
24994     * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
24995     *
24996     * @return the tooltip text
24997     * @see #setTooltipText(CharSequence)
24998     * @attr ref android.R.styleable#View_tooltipText
24999     */
25000    @Nullable
25001    public CharSequence getTooltipText() {
25002        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
25003    }
25004
25005    /**
25006     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25007     */
25008    @Nullable
25009    public CharSequence getTooltip() {
25010        return getTooltipText();
25011    }
25012
25013    private boolean showTooltip(int x, int y, boolean fromLongClick) {
25014        if (mAttachInfo == null || mTooltipInfo == null) {
25015            return false;
25016        }
25017        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
25018            return false;
25019        }
25020        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
25021            return false;
25022        }
25023        hideTooltip();
25024        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
25025        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
25026        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
25027        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
25028        mAttachInfo.mTooltipHost = this;
25029        return true;
25030    }
25031
25032    void hideTooltip() {
25033        if (mTooltipInfo == null) {
25034            return;
25035        }
25036        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25037        if (mTooltipInfo.mTooltipPopup == null) {
25038            return;
25039        }
25040        mTooltipInfo.mTooltipPopup.hide();
25041        mTooltipInfo.mTooltipPopup = null;
25042        mTooltipInfo.mTooltipFromLongClick = false;
25043        if (mAttachInfo != null) {
25044            mAttachInfo.mTooltipHost = null;
25045        }
25046    }
25047
25048    private boolean showLongClickTooltip(int x, int y) {
25049        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25050        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25051        return showTooltip(x, y, true);
25052    }
25053
25054    private void showHoverTooltip() {
25055        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
25056    }
25057
25058    boolean dispatchTooltipHoverEvent(MotionEvent event) {
25059        if (mTooltipInfo == null) {
25060            return false;
25061        }
25062        switch(event.getAction()) {
25063            case MotionEvent.ACTION_HOVER_MOVE:
25064                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
25065                    break;
25066                }
25067                if (!mTooltipInfo.mTooltipFromLongClick) {
25068                    if (mTooltipInfo.mTooltipPopup == null) {
25069                        // Schedule showing the tooltip after a timeout.
25070                        mTooltipInfo.mAnchorX = (int) event.getX();
25071                        mTooltipInfo.mAnchorY = (int) event.getY();
25072                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25073                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
25074                                ViewConfiguration.getHoverTooltipShowTimeout());
25075                    }
25076
25077                    // Hide hover-triggered tooltip after a period of inactivity.
25078                    // Match the timeout used by NativeInputManager to hide the mouse pointer
25079                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
25080                    final int timeout;
25081                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
25082                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
25083                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
25084                    } else {
25085                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
25086                    }
25087                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25088                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
25089                }
25090                return true;
25091
25092            case MotionEvent.ACTION_HOVER_EXIT:
25093                if (!mTooltipInfo.mTooltipFromLongClick) {
25094                    hideTooltip();
25095                }
25096                break;
25097        }
25098        return false;
25099    }
25100
25101    void handleTooltipKey(KeyEvent event) {
25102        switch (event.getAction()) {
25103            case KeyEvent.ACTION_DOWN:
25104                if (event.getRepeatCount() == 0) {
25105                    hideTooltip();
25106                }
25107                break;
25108
25109            case KeyEvent.ACTION_UP:
25110                handleTooltipUp();
25111                break;
25112        }
25113    }
25114
25115    private void handleTooltipUp() {
25116        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
25117            return;
25118        }
25119        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25120        postDelayed(mTooltipInfo.mHideTooltipRunnable,
25121                ViewConfiguration.getLongPressTooltipHideTimeout());
25122    }
25123
25124    private int getFocusableAttribute(TypedArray attributes) {
25125        TypedValue val = new TypedValue();
25126        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
25127            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
25128                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
25129            } else {
25130                return val.data;
25131            }
25132        } else {
25133            return FOCUSABLE_AUTO;
25134        }
25135    }
25136
25137    /**
25138     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
25139     * is not showing.
25140     * @hide
25141     */
25142    @TestApi
25143    public View getTooltipView() {
25144        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
25145            return null;
25146        }
25147        return mTooltipInfo.mTooltipPopup.getContentView();
25148    }
25149}
25150