View.java revision 85cee7ab388fda5393bac3b268cc15780579da39
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.net.Uri;
65import android.os.Build;
66import android.os.Bundle;
67import android.os.Handler;
68import android.os.IBinder;
69import android.os.Message;
70import android.os.Parcel;
71import android.os.Parcelable;
72import android.os.RemoteException;
73import android.os.SystemClock;
74import android.os.SystemProperties;
75import android.os.Trace;
76import android.text.TextUtils;
77import android.util.AttributeSet;
78import android.util.FloatProperty;
79import android.util.LayoutDirection;
80import android.util.Log;
81import android.util.LongSparseLongArray;
82import android.util.Pools.SynchronizedPool;
83import android.util.Property;
84import android.util.SparseArray;
85import android.util.StateSet;
86import android.util.SuperNotCalledException;
87import android.util.TypedValue;
88import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
89import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
90import android.view.AccessibilityIterators.TextSegmentIterator;
91import android.view.AccessibilityIterators.WordTextSegmentIterator;
92import android.view.ContextMenu.ContextMenuInfo;
93import android.view.accessibility.AccessibilityEvent;
94import android.view.accessibility.AccessibilityEventSource;
95import android.view.accessibility.AccessibilityManager;
96import android.view.accessibility.AccessibilityNodeInfo;
97import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
98import android.view.accessibility.AccessibilityNodeProvider;
99import android.view.accessibility.AccessibilityWindowInfo;
100import android.view.animation.Animation;
101import android.view.animation.AnimationUtils;
102import android.view.animation.Transformation;
103import android.view.autofill.AutofillManager;
104import android.view.autofill.AutofillValue;
105import android.view.inputmethod.EditorInfo;
106import android.view.inputmethod.InputConnection;
107import android.view.inputmethod.InputMethodManager;
108import android.widget.Checkable;
109import android.widget.FrameLayout;
110import android.widget.ScrollBarDrawable;
111
112import com.android.internal.R;
113import com.android.internal.view.TooltipPopup;
114import com.android.internal.view.menu.MenuBuilder;
115import com.android.internal.widget.ScrollBarUtils;
116
117import com.google.android.collect.Lists;
118import com.google.android.collect.Maps;
119
120import java.lang.annotation.Retention;
121import java.lang.annotation.RetentionPolicy;
122import java.lang.ref.WeakReference;
123import java.lang.reflect.Field;
124import java.lang.reflect.InvocationTargetException;
125import java.lang.reflect.Method;
126import java.lang.reflect.Modifier;
127import java.util.ArrayList;
128import java.util.Arrays;
129import java.util.Collection;
130import java.util.Collections;
131import java.util.HashMap;
132import java.util.List;
133import java.util.Locale;
134import java.util.Map;
135import java.util.concurrent.CopyOnWriteArrayList;
136import java.util.concurrent.atomic.AtomicInteger;
137import java.util.function.Predicate;
138
139/**
140 * <p>
141 * This class represents the basic building block for user interface components. A View
142 * occupies a rectangular area on the screen and is responsible for drawing and
143 * event handling. View is the base class for <em>widgets</em>, which are
144 * used to create interactive UI components (buttons, text fields, etc.). The
145 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
146 * are invisible containers that hold other Views (or other ViewGroups) and define
147 * their layout properties.
148 * </p>
149 *
150 * <div class="special reference">
151 * <h3>Developer Guides</h3>
152 * <p>For information about using this class to develop your application's user interface,
153 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
154 * </div>
155 *
156 * <a name="Using"></a>
157 * <h3>Using Views</h3>
158 * <p>
159 * All of the views in a window are arranged in a single tree. You can add views
160 * either from code or by specifying a tree of views in one or more XML layout
161 * files. There are many specialized subclasses of views that act as controls or
162 * are capable of displaying text, images, or other content.
163 * </p>
164 * <p>
165 * Once you have created a tree of views, there are typically a few types of
166 * common operations you may wish to perform:
167 * <ul>
168 * <li><strong>Set properties:</strong> for example setting the text of a
169 * {@link android.widget.TextView}. The available properties and the methods
170 * that set them will vary among the different subclasses of views. Note that
171 * properties that are known at build time can be set in the XML layout
172 * files.</li>
173 * <li><strong>Set focus:</strong> The framework will handle moving focus in
174 * response to user input. To force focus to a specific view, call
175 * {@link #requestFocus}.</li>
176 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
177 * that will be notified when something interesting happens to the view. For
178 * example, all views will let you set a listener to be notified when the view
179 * gains or loses focus. You can register such a listener using
180 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
181 * Other view subclasses offer more specialized listeners. For example, a Button
182 * exposes a listener to notify clients when the button is clicked.</li>
183 * <li><strong>Set visibility:</strong> You can hide or show views using
184 * {@link #setVisibility(int)}.</li>
185 * </ul>
186 * </p>
187 * <p><em>
188 * Note: The Android framework is responsible for measuring, laying out and
189 * drawing views. You should not call methods that perform these actions on
190 * views yourself unless you are actually implementing a
191 * {@link android.view.ViewGroup}.
192 * </em></p>
193 *
194 * <a name="Lifecycle"></a>
195 * <h3>Implementing a Custom View</h3>
196 *
197 * <p>
198 * To implement a custom view, you will usually begin by providing overrides for
199 * some of the standard methods that the framework calls on all views. You do
200 * not need to override all of these methods. In fact, you can start by just
201 * overriding {@link #onDraw(android.graphics.Canvas)}.
202 * <table border="2" width="85%" align="center" cellpadding="5">
203 *     <thead>
204 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
205 *     </thead>
206 *
207 *     <tbody>
208 *     <tr>
209 *         <td rowspan="2">Creation</td>
210 *         <td>Constructors</td>
211 *         <td>There is a form of the constructor that are called when the view
212 *         is created from code and a form that is called when the view is
213 *         inflated from a layout file. The second form should parse and apply
214 *         any attributes defined in the layout file.
215 *         </td>
216 *     </tr>
217 *     <tr>
218 *         <td><code>{@link #onFinishInflate()}</code></td>
219 *         <td>Called after a view and all of its children has been inflated
220 *         from XML.</td>
221 *     </tr>
222 *
223 *     <tr>
224 *         <td rowspan="3">Layout</td>
225 *         <td><code>{@link #onMeasure(int, int)}</code></td>
226 *         <td>Called to determine the size requirements for this view and all
227 *         of its children.
228 *         </td>
229 *     </tr>
230 *     <tr>
231 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
232 *         <td>Called when this view should assign a size and position to all
233 *         of its children.
234 *         </td>
235 *     </tr>
236 *     <tr>
237 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
238 *         <td>Called when the size of this view has changed.
239 *         </td>
240 *     </tr>
241 *
242 *     <tr>
243 *         <td>Drawing</td>
244 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
245 *         <td>Called when the view should render its content.
246 *         </td>
247 *     </tr>
248 *
249 *     <tr>
250 *         <td rowspan="4">Event processing</td>
251 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
252 *         <td>Called when a new hardware key event occurs.
253 *         </td>
254 *     </tr>
255 *     <tr>
256 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
257 *         <td>Called when a hardware key up event occurs.
258 *         </td>
259 *     </tr>
260 *     <tr>
261 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
262 *         <td>Called when a trackball motion event occurs.
263 *         </td>
264 *     </tr>
265 *     <tr>
266 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
267 *         <td>Called when a touch screen motion event occurs.
268 *         </td>
269 *     </tr>
270 *
271 *     <tr>
272 *         <td rowspan="2">Focus</td>
273 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
274 *         <td>Called when the view gains or loses focus.
275 *         </td>
276 *     </tr>
277 *
278 *     <tr>
279 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
280 *         <td>Called when the window containing the view gains or loses focus.
281 *         </td>
282 *     </tr>
283 *
284 *     <tr>
285 *         <td rowspan="3">Attaching</td>
286 *         <td><code>{@link #onAttachedToWindow()}</code></td>
287 *         <td>Called when the view is attached to a window.
288 *         </td>
289 *     </tr>
290 *
291 *     <tr>
292 *         <td><code>{@link #onDetachedFromWindow}</code></td>
293 *         <td>Called when the view is detached from its window.
294 *         </td>
295 *     </tr>
296 *
297 *     <tr>
298 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
299 *         <td>Called when the visibility of the window containing the view
300 *         has changed.
301 *         </td>
302 *     </tr>
303 *     </tbody>
304 *
305 * </table>
306 * </p>
307 *
308 * <a name="IDs"></a>
309 * <h3>IDs</h3>
310 * Views may have an integer id associated with them. These ids are typically
311 * assigned in the layout XML files, and are used to find specific views within
312 * the view tree. A common pattern is to:
313 * <ul>
314 * <li>Define a Button in the layout file and assign it a unique ID.
315 * <pre>
316 * &lt;Button
317 *     android:id="@+id/my_button"
318 *     android:layout_width="wrap_content"
319 *     android:layout_height="wrap_content"
320 *     android:text="@string/my_button_text"/&gt;
321 * </pre></li>
322 * <li>From the onCreate method of an Activity, find the Button
323 * <pre class="prettyprint">
324 *      Button myButton = findViewById(R.id.my_button);
325 * </pre></li>
326 * </ul>
327 * <p>
328 * View IDs need not be unique throughout the tree, but it is good practice to
329 * ensure that they are at least unique within the part of the tree you are
330 * searching.
331 * </p>
332 *
333 * <a name="Position"></a>
334 * <h3>Position</h3>
335 * <p>
336 * The geometry of a view is that of a rectangle. A view has a location,
337 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
338 * two dimensions, expressed as a width and a height. The unit for location
339 * and dimensions is the pixel.
340 * </p>
341 *
342 * <p>
343 * It is possible to retrieve the location of a view by invoking the methods
344 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
345 * coordinate of the rectangle representing the view. The latter returns the
346 * top, or Y, coordinate of the rectangle representing the view. These methods
347 * both return the location of the view relative to its parent. For instance,
348 * when getLeft() returns 20, that means the view is located 20 pixels to the
349 * right of the left edge of its direct parent.
350 * </p>
351 *
352 * <p>
353 * In addition, several convenience methods are offered to avoid unnecessary
354 * computations, namely {@link #getRight()} and {@link #getBottom()}.
355 * These methods return the coordinates of the right and bottom edges of the
356 * rectangle representing the view. For instance, calling {@link #getRight()}
357 * is similar to the following computation: <code>getLeft() + getWidth()</code>
358 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
359 * </p>
360 *
361 * <a name="SizePaddingMargins"></a>
362 * <h3>Size, padding and margins</h3>
363 * <p>
364 * The size of a view is expressed with a width and a height. A view actually
365 * possess two pairs of width and height values.
366 * </p>
367 *
368 * <p>
369 * The first pair is known as <em>measured width</em> and
370 * <em>measured height</em>. These dimensions define how big a view wants to be
371 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
372 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
373 * and {@link #getMeasuredHeight()}.
374 * </p>
375 *
376 * <p>
377 * The second pair is simply known as <em>width</em> and <em>height</em>, or
378 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
379 * dimensions define the actual size of the view on screen, at drawing time and
380 * after layout. These values may, but do not have to, be different from the
381 * measured width and height. The width and height can be obtained by calling
382 * {@link #getWidth()} and {@link #getHeight()}.
383 * </p>
384 *
385 * <p>
386 * To measure its dimensions, a view takes into account its padding. The padding
387 * is expressed in pixels for the left, top, right and bottom parts of the view.
388 * Padding can be used to offset the content of the view by a specific amount of
389 * pixels. For instance, a left padding of 2 will push the view's content by
390 * 2 pixels to the right of the left edge. Padding can be set using the
391 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
392 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
393 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
394 * {@link #getPaddingEnd()}.
395 * </p>
396 *
397 * <p>
398 * Even though a view can define a padding, it does not provide any support for
399 * margins. However, view groups provide such a support. Refer to
400 * {@link android.view.ViewGroup} and
401 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
402 * </p>
403 *
404 * <a name="Layout"></a>
405 * <h3>Layout</h3>
406 * <p>
407 * Layout is a two pass process: a measure pass and a layout pass. The measuring
408 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
409 * of the view tree. Each view pushes dimension specifications down the tree
410 * during the recursion. At the end of the measure pass, every view has stored
411 * its measurements. The second pass happens in
412 * {@link #layout(int,int,int,int)} and is also top-down. During
413 * this pass each parent is responsible for positioning all of its children
414 * using the sizes computed in the measure pass.
415 * </p>
416 *
417 * <p>
418 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
419 * {@link #getMeasuredHeight()} values must be set, along with those for all of
420 * that view's descendants. A view's measured width and measured height values
421 * must respect the constraints imposed by the view's parents. This guarantees
422 * that at the end of the measure pass, all parents accept all of their
423 * children's measurements. A parent view may call measure() more than once on
424 * its children. For example, the parent may measure each child once with
425 * unspecified dimensions to find out how big they want to be, then call
426 * measure() on them again with actual numbers if the sum of all the children's
427 * unconstrained sizes is too big or too small.
428 * </p>
429 *
430 * <p>
431 * The measure pass uses two classes to communicate dimensions. The
432 * {@link MeasureSpec} class is used by views to tell their parents how they
433 * want to be measured and positioned. The base LayoutParams class just
434 * describes how big the view wants to be for both width and height. For each
435 * dimension, it can specify one of:
436 * <ul>
437 * <li> an exact number
438 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
439 * (minus padding)
440 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
441 * enclose its content (plus padding).
442 * </ul>
443 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
444 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
445 * an X and Y value.
446 * </p>
447 *
448 * <p>
449 * MeasureSpecs are used to push requirements down the tree from parent to
450 * child. A MeasureSpec can be in one of three modes:
451 * <ul>
452 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
453 * of a child view. For example, a LinearLayout may call measure() on its child
454 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
455 * tall the child view wants to be given a width of 240 pixels.
456 * <li>EXACTLY: This is used by the parent to impose an exact size on the
457 * child. The child must use this size, and guarantee that all of its
458 * descendants will fit within this size.
459 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
460 * child. The child must guarantee that it and all of its descendants will fit
461 * within this size.
462 * </ul>
463 * </p>
464 *
465 * <p>
466 * To initiate a layout, call {@link #requestLayout}. This method is typically
467 * called by a view on itself when it believes that is can no longer fit within
468 * its current bounds.
469 * </p>
470 *
471 * <a name="Drawing"></a>
472 * <h3>Drawing</h3>
473 * <p>
474 * Drawing is handled by walking the tree and recording the drawing commands of
475 * any View that needs to update. After this, the drawing commands of the
476 * entire tree are issued to screen, clipped to the newly damaged area.
477 * </p>
478 *
479 * <p>
480 * The tree is largely recorded and drawn in order, with parents drawn before
481 * (i.e., behind) their children, with siblings drawn in the order they appear
482 * in the tree. If you set a background drawable for a View, then the View will
483 * draw it before calling back to its <code>onDraw()</code> method. The child
484 * drawing order can be overridden with
485 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
486 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
487 * </p>
488 *
489 * <p>
490 * To force a view to draw, call {@link #invalidate()}.
491 * </p>
492 *
493 * <a name="EventHandlingThreading"></a>
494 * <h3>Event Handling and Threading</h3>
495 * <p>
496 * The basic cycle of a view is as follows:
497 * <ol>
498 * <li>An event comes in and is dispatched to the appropriate view. The view
499 * handles the event and notifies any listeners.</li>
500 * <li>If in the course of processing the event, the view's bounds may need
501 * to be changed, the view will call {@link #requestLayout()}.</li>
502 * <li>Similarly, if in the course of processing the event the view's appearance
503 * may need to be changed, the view will call {@link #invalidate()}.</li>
504 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
505 * the framework will take care of measuring, laying out, and drawing the tree
506 * as appropriate.</li>
507 * </ol>
508 * </p>
509 *
510 * <p><em>Note: The entire view tree is single threaded. You must always be on
511 * the UI thread when calling any method on any view.</em>
512 * If you are doing work on other threads and want to update the state of a view
513 * from that thread, you should use a {@link Handler}.
514 * </p>
515 *
516 * <a name="FocusHandling"></a>
517 * <h3>Focus Handling</h3>
518 * <p>
519 * The framework will handle routine focus movement in response to user input.
520 * This includes changing the focus as views are removed or hidden, or as new
521 * views become available. Views indicate their willingness to take focus
522 * through the {@link #isFocusable} method. To change whether a view can take
523 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
524 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
525 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
526 * </p>
527 * <p>
528 * Focus movement is based on an algorithm which finds the nearest neighbor in a
529 * given direction. In rare cases, the default algorithm may not match the
530 * intended behavior of the developer. In these situations, you can provide
531 * explicit overrides by using these XML attributes in the layout file:
532 * <pre>
533 * nextFocusDown
534 * nextFocusLeft
535 * nextFocusRight
536 * nextFocusUp
537 * </pre>
538 * </p>
539 *
540 *
541 * <p>
542 * To get a particular view to take focus, call {@link #requestFocus()}.
543 * </p>
544 *
545 * <a name="TouchMode"></a>
546 * <h3>Touch Mode</h3>
547 * <p>
548 * When a user is navigating a user interface via directional keys such as a D-pad, it is
549 * necessary to give focus to actionable items such as buttons so the user can see
550 * what will take input.  If the device has touch capabilities, however, and the user
551 * begins interacting with the interface by touching it, it is no longer necessary to
552 * always highlight, or give focus to, a particular view.  This motivates a mode
553 * for interaction named 'touch mode'.
554 * </p>
555 * <p>
556 * For a touch capable device, once the user touches the screen, the device
557 * will enter touch mode.  From this point onward, only views for which
558 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
559 * Other views that are touchable, like buttons, will not take focus when touched; they will
560 * only fire the on click listeners.
561 * </p>
562 * <p>
563 * Any time a user hits a directional key, such as a D-pad direction, the view device will
564 * exit touch mode, and find a view to take focus, so that the user may resume interacting
565 * with the user interface without touching the screen again.
566 * </p>
567 * <p>
568 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
569 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
570 * </p>
571 *
572 * <a name="Scrolling"></a>
573 * <h3>Scrolling</h3>
574 * <p>
575 * The framework provides basic support for views that wish to internally
576 * scroll their content. This includes keeping track of the X and Y scroll
577 * offset as well as mechanisms for drawing scrollbars. See
578 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
579 * {@link #awakenScrollBars()} for more details.
580 * </p>
581 *
582 * <a name="Tags"></a>
583 * <h3>Tags</h3>
584 * <p>
585 * Unlike IDs, tags are not used to identify views. Tags are essentially an
586 * extra piece of information that can be associated with a view. They are most
587 * often used as a convenience to store data related to views in the views
588 * themselves rather than by putting them in a separate structure.
589 * </p>
590 * <p>
591 * Tags may be specified with character sequence values in layout XML as either
592 * a single tag using the {@link android.R.styleable#View_tag android:tag}
593 * attribute or multiple tags using the {@code <tag>} child element:
594 * <pre>
595 *     &ltView ...
596 *           android:tag="@string/mytag_value" /&gt;
597 *     &ltView ...&gt;
598 *         &lttag android:id="@+id/mytag"
599 *              android:value="@string/mytag_value" /&gt;
600 *     &lt/View>
601 * </pre>
602 * </p>
603 * <p>
604 * Tags may also be specified with arbitrary objects from code using
605 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
606 * </p>
607 *
608 * <a name="Themes"></a>
609 * <h3>Themes</h3>
610 * <p>
611 * By default, Views are created using the theme of the Context object supplied
612 * to their constructor; however, a different theme may be specified by using
613 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
614 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
615 * code.
616 * </p>
617 * <p>
618 * When the {@link android.R.styleable#View_theme android:theme} attribute is
619 * used in XML, the specified theme is applied on top of the inflation
620 * context's theme (see {@link LayoutInflater}) and used for the view itself as
621 * well as any child elements.
622 * </p>
623 * <p>
624 * In the following example, both views will be created using the Material dark
625 * color scheme; however, because an overlay theme is used which only defines a
626 * subset of attributes, the value of
627 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
628 * the inflation context's theme (e.g. the Activity theme) will be preserved.
629 * <pre>
630 *     &ltLinearLayout
631 *             ...
632 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
633 *         &ltView ...&gt;
634 *     &lt/LinearLayout&gt;
635 * </pre>
636 * </p>
637 *
638 * <a name="Properties"></a>
639 * <h3>Properties</h3>
640 * <p>
641 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
642 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
643 * available both in the {@link Property} form as well as in similarly-named setter/getter
644 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
645 * be used to set persistent state associated with these rendering-related properties on the view.
646 * The properties and methods can also be used in conjunction with
647 * {@link android.animation.Animator Animator}-based animations, described more in the
648 * <a href="#Animation">Animation</a> section.
649 * </p>
650 *
651 * <a name="Animation"></a>
652 * <h3>Animation</h3>
653 * <p>
654 * Starting with Android 3.0, the preferred way of animating views is to use the
655 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
656 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
657 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
658 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
659 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
660 * makes animating these View properties particularly easy and efficient.
661 * </p>
662 * <p>
663 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
664 * You can attach an {@link Animation} object to a view using
665 * {@link #setAnimation(Animation)} or
666 * {@link #startAnimation(Animation)}. The animation can alter the scale,
667 * rotation, translation and alpha of a view over time. If the animation is
668 * attached to a view that has children, the animation will affect the entire
669 * subtree rooted by that node. When an animation is started, the framework will
670 * take care of redrawing the appropriate views until the animation completes.
671 * </p>
672 *
673 * <a name="Security"></a>
674 * <h3>Security</h3>
675 * <p>
676 * Sometimes it is essential that an application be able to verify that an action
677 * is being performed with the full knowledge and consent of the user, such as
678 * granting a permission request, making a purchase or clicking on an advertisement.
679 * Unfortunately, a malicious application could try to spoof the user into
680 * performing these actions, unaware, by concealing the intended purpose of the view.
681 * As a remedy, the framework offers a touch filtering mechanism that can be used to
682 * improve the security of views that provide access to sensitive functionality.
683 * </p><p>
684 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
685 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
686 * will discard touches that are received whenever the view's window is obscured by
687 * another visible window.  As a result, the view will not receive touches whenever a
688 * toast, dialog or other window appears above the view's window.
689 * </p><p>
690 * For more fine-grained control over security, consider overriding the
691 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
692 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
693 * </p>
694 *
695 * @attr ref android.R.styleable#View_alpha
696 * @attr ref android.R.styleable#View_background
697 * @attr ref android.R.styleable#View_clickable
698 * @attr ref android.R.styleable#View_contentDescription
699 * @attr ref android.R.styleable#View_drawingCacheQuality
700 * @attr ref android.R.styleable#View_duplicateParentState
701 * @attr ref android.R.styleable#View_id
702 * @attr ref android.R.styleable#View_requiresFadingEdge
703 * @attr ref android.R.styleable#View_fadeScrollbars
704 * @attr ref android.R.styleable#View_fadingEdgeLength
705 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
706 * @attr ref android.R.styleable#View_fitsSystemWindows
707 * @attr ref android.R.styleable#View_isScrollContainer
708 * @attr ref android.R.styleable#View_focusable
709 * @attr ref android.R.styleable#View_focusableInTouchMode
710 * @attr ref android.R.styleable#View_focusedByDefault
711 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
712 * @attr ref android.R.styleable#View_keepScreenOn
713 * @attr ref android.R.styleable#View_keyboardNavigationCluster
714 * @attr ref android.R.styleable#View_layerType
715 * @attr ref android.R.styleable#View_layoutDirection
716 * @attr ref android.R.styleable#View_longClickable
717 * @attr ref android.R.styleable#View_minHeight
718 * @attr ref android.R.styleable#View_minWidth
719 * @attr ref android.R.styleable#View_nextClusterForward
720 * @attr ref android.R.styleable#View_nextFocusDown
721 * @attr ref android.R.styleable#View_nextFocusLeft
722 * @attr ref android.R.styleable#View_nextFocusRight
723 * @attr ref android.R.styleable#View_nextFocusUp
724 * @attr ref android.R.styleable#View_onClick
725 * @attr ref android.R.styleable#View_padding
726 * @attr ref android.R.styleable#View_paddingBottom
727 * @attr ref android.R.styleable#View_paddingLeft
728 * @attr ref android.R.styleable#View_paddingRight
729 * @attr ref android.R.styleable#View_paddingTop
730 * @attr ref android.R.styleable#View_paddingStart
731 * @attr ref android.R.styleable#View_paddingEnd
732 * @attr ref android.R.styleable#View_saveEnabled
733 * @attr ref android.R.styleable#View_rotation
734 * @attr ref android.R.styleable#View_rotationX
735 * @attr ref android.R.styleable#View_rotationY
736 * @attr ref android.R.styleable#View_scaleX
737 * @attr ref android.R.styleable#View_scaleY
738 * @attr ref android.R.styleable#View_scrollX
739 * @attr ref android.R.styleable#View_scrollY
740 * @attr ref android.R.styleable#View_scrollbarSize
741 * @attr ref android.R.styleable#View_scrollbarStyle
742 * @attr ref android.R.styleable#View_scrollbars
743 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
744 * @attr ref android.R.styleable#View_scrollbarFadeDuration
745 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
746 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
747 * @attr ref android.R.styleable#View_scrollbarThumbVertical
748 * @attr ref android.R.styleable#View_scrollbarTrackVertical
749 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
750 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
751 * @attr ref android.R.styleable#View_stateListAnimator
752 * @attr ref android.R.styleable#View_transitionName
753 * @attr ref android.R.styleable#View_soundEffectsEnabled
754 * @attr ref android.R.styleable#View_tag
755 * @attr ref android.R.styleable#View_textAlignment
756 * @attr ref android.R.styleable#View_textDirection
757 * @attr ref android.R.styleable#View_transformPivotX
758 * @attr ref android.R.styleable#View_transformPivotY
759 * @attr ref android.R.styleable#View_translationX
760 * @attr ref android.R.styleable#View_translationY
761 * @attr ref android.R.styleable#View_translationZ
762 * @attr ref android.R.styleable#View_visibility
763 * @attr ref android.R.styleable#View_theme
764 *
765 * @see android.view.ViewGroup
766 */
767@UiThread
768public class View implements Drawable.Callback, KeyEvent.Callback,
769        AccessibilityEventSource {
770    private static final boolean DBG = false;
771
772    /** @hide */
773    public static boolean DEBUG_DRAW = false;
774
775    /**
776     * The logging tag used by this class with android.util.Log.
777     */
778    protected static final String VIEW_LOG_TAG = "View";
779
780    /**
781     * When set to true, apps will draw debugging information about their layouts.
782     *
783     * @hide
784     */
785    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
786
787    /**
788     * When set to true, this view will save its attribute data.
789     *
790     * @hide
791     */
792    public static boolean mDebugViewAttributes = false;
793
794    /**
795     * Used to mark a View that has no ID.
796     */
797    public static final int NO_ID = -1;
798
799    /**
800     * Last ID that is given to Views that are no part of activities.
801     *
802     * {@hide}
803     */
804    public static final int LAST_APP_ACCESSIBILITY_ID = Integer.MAX_VALUE / 2;
805
806    /**
807     * Signals that compatibility booleans have been initialized according to
808     * target SDK versions.
809     */
810    private static boolean sCompatibilityDone = false;
811
812    /**
813     * Use the old (broken) way of building MeasureSpecs.
814     */
815    private static boolean sUseBrokenMakeMeasureSpec = false;
816
817    /**
818     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
819     */
820    static boolean sUseZeroUnspecifiedMeasureSpec = false;
821
822    /**
823     * Ignore any optimizations using the measure cache.
824     */
825    private static boolean sIgnoreMeasureCache = false;
826
827    /**
828     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
829     */
830    private static boolean sAlwaysRemeasureExactly = false;
831
832    /**
833     * Relax constraints around whether setLayoutParams() must be called after
834     * modifying the layout params.
835     */
836    private static boolean sLayoutParamsAlwaysChanged = false;
837
838    /**
839     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
840     * without throwing
841     */
842    static boolean sTextureViewIgnoresDrawableSetters = false;
843
844    /**
845     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
846     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
847     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
848     * check is implemented for backwards compatibility.
849     *
850     * {@hide}
851     */
852    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
853
854    /**
855     * Prior to N, when drag enters into child of a view that has already received an
856     * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
857     * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
858     * false from its event handler for these events.
859     * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
860     * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
861     * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
862     */
863    static boolean sCascadedDragDrop;
864
865    /**
866     * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
867     * to determine things like whether or not to permit item click events. We can't break
868     * apps that do this just because more things (clickable things) are now auto-focusable
869     * and they would get different results, so give old behavior to old apps.
870     */
871    static boolean sHasFocusableExcludeAutoFocusable;
872
873    /**
874     * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
875     * made focusable by default. As a result, apps could (incorrectly) change the clickable
876     * setting of views off the UI thread. Now that clickable can effect the focusable state,
877     * changing the clickable attribute off the UI thread will cause an exception (since changing
878     * the focusable state checks). In order to prevent apps from crashing, we will handle this
879     * specific case and just not notify parents on new focusables resulting from marking views
880     * clickable from outside the UI thread.
881     */
882    private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
883
884    /** @hide */
885    @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
886    @Retention(RetentionPolicy.SOURCE)
887    public @interface Focusable {}
888
889    /**
890     * This view does not want keystrokes.
891     * <p>
892     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
893     * android:focusable}.
894     */
895    public static final int NOT_FOCUSABLE = 0x00000000;
896
897    /**
898     * This view wants keystrokes.
899     * <p>
900     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
901     * android:focusable}.
902     */
903    public static final int FOCUSABLE = 0x00000001;
904
905    /**
906     * This view determines focusability automatically. This is the default.
907     * <p>
908     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
909     * android:focusable}.
910     */
911    public static final int FOCUSABLE_AUTO = 0x00000010;
912
913    /**
914     * Mask for use with setFlags indicating bits used for focus.
915     */
916    private static final int FOCUSABLE_MASK = 0x00000011;
917
918    /**
919     * This view will adjust its padding to fit sytem windows (e.g. status bar)
920     */
921    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
922
923    /** @hide */
924    @IntDef({VISIBLE, INVISIBLE, GONE})
925    @Retention(RetentionPolicy.SOURCE)
926    public @interface Visibility {}
927
928    /**
929     * This view is visible.
930     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
931     * android:visibility}.
932     */
933    public static final int VISIBLE = 0x00000000;
934
935    /**
936     * This view is invisible, but it still takes up space for layout purposes.
937     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
938     * android:visibility}.
939     */
940    public static final int INVISIBLE = 0x00000004;
941
942    /**
943     * This view is invisible, and it doesn't take any space for layout
944     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
945     * android:visibility}.
946     */
947    public static final int GONE = 0x00000008;
948
949    /**
950     * Mask for use with setFlags indicating bits used for visibility.
951     * {@hide}
952     */
953    static final int VISIBILITY_MASK = 0x0000000C;
954
955    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
956
957    /**
958     * This view contains an email address.
959     *
960     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_EMAIL_ADDRESS}"
961     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
962     */
963    public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
964
965    /**
966     * The view contains a real name.
967     *
968     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_NAME}" to
969     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
970     */
971    public static final String AUTOFILL_HINT_NAME = "name";
972
973    /**
974     * The view contains a user name.
975     *
976     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_USERNAME}" to
977     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
978     */
979    public static final String AUTOFILL_HINT_USERNAME = "username";
980
981    /**
982     * The view contains a password.
983     *
984     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_PASSWORD}" to
985     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
986     */
987    public static final String AUTOFILL_HINT_PASSWORD = "password";
988
989    /**
990     * The view contains a phone number.
991     *
992     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_PHONE}" to
993     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
994     */
995    public static final String AUTOFILL_HINT_PHONE = "phone";
996
997    /**
998     * The view contains a postal address.
999     *
1000     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_ADDRESS}"
1001     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1002     */
1003    public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1004
1005    /**
1006     * The view contains a postal code.
1007     *
1008     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_CODE}" to
1009     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
1010     */
1011    public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1012
1013    /**
1014     * The view contains a credit card number.
1015     *
1016     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1017     * #AUTOFILL_HINT_CREDIT_CARD_NUMBER}" to <a href="#attr_android:autofillHint"> {@code
1018     * android:autofillHint}.
1019     */
1020    public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1021
1022    /**
1023     * The view contains a credit card security code.
1024     *
1025     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1026     * #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}" to <a href="#attr_android:autofillHint"> {@code
1027     * android:autofillHint}.
1028     */
1029    public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1030
1031    /**
1032     * The view contains a credit card expiration date.
1033     *
1034     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1035     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}" to <a href="#attr_android:autofillHint"> {@code
1036     * android:autofillHint}.
1037     */
1038    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1039            "creditCardExpirationDate";
1040
1041    /**
1042     * The view contains the month a credit card expires.
1043     *
1044     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1045     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}" to <a href="#attr_android:autofillHint"> {@code
1046     * android:autofillHint}.
1047     */
1048    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1049            "creditCardExpirationMonth";
1050
1051    /**
1052     * The view contains the year a credit card expires.
1053     *
1054     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1055     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}" to <a href="#attr_android:autofillHint"> {@code
1056     * android:autofillHint}.
1057     */
1058    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1059            "creditCardExpirationYear";
1060
1061    /**
1062     * The view contains the day a credit card expires.
1063     *
1064     * Use with {@link #setAutofillHints(String[])}, or set "{@value
1065     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}" to <a href="#attr_android:autofillHint"> {@code
1066     * android:autofillHint}.
1067     */
1068    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1069
1070    /**
1071     * Hintd for the autofill services that describes the content of the view.
1072     */
1073    private @Nullable String[] mAutofillHints;
1074
1075    /** @hide */
1076    @IntDef({
1077            AUTOFILL_TYPE_NONE,
1078            AUTOFILL_TYPE_TEXT,
1079            AUTOFILL_TYPE_TOGGLE,
1080            AUTOFILL_TYPE_LIST,
1081            AUTOFILL_TYPE_DATE
1082    })
1083    @Retention(RetentionPolicy.SOURCE)
1084    public @interface AutofillType {}
1085
1086    /**
1087     * Autofill type for views that cannot be autofilled.
1088     */
1089    public static final int AUTOFILL_TYPE_NONE = 0;
1090
1091    /**
1092     * Autofill type for a text field, which is filled by a {@link CharSequence}.
1093     *
1094     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1095     * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1096     * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1097     */
1098    public static final int AUTOFILL_TYPE_TEXT = 1;
1099
1100    /**
1101     * Autofill type for a togglable field, which is filled by a {@code boolean}.
1102     *
1103     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1104     * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1105     * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1106     */
1107    public static final int AUTOFILL_TYPE_TOGGLE = 2;
1108
1109    /**
1110     * Autofill type for a selection list field, which is filled by an {@code int}
1111     * representing the element index inside the list (starting at {@code 0}).
1112     *
1113     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1114     * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1115     * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1116     *
1117     * <p>The available options in the selection list are typically provided by
1118     * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1119     */
1120    public static final int AUTOFILL_TYPE_LIST = 3;
1121
1122
1123    /**
1124     * Autofill type for a field that contains a date, which is represented by a long representing
1125     * the number of milliseconds since the standard base time known as "the epoch", namely
1126     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1127     *
1128     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1129     * {@link AutofillValue#forDate(long)}, and the values passed to
1130     * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1131     */
1132    public static final int AUTOFILL_TYPE_DATE = 4;
1133
1134    /** @hide */
1135    @IntDef({
1136            IMPORTANT_FOR_AUTOFILL_AUTO,
1137            IMPORTANT_FOR_AUTOFILL_YES,
1138            IMPORTANT_FOR_AUTOFILL_NO,
1139            IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1140            IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1141    })
1142    @Retention(RetentionPolicy.SOURCE)
1143    public @interface AutofillImportance {}
1144
1145    /**
1146     * Automatically determine whether a view is important for autofill.
1147     */
1148    public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1149
1150    /**
1151     * The view is important for autofill, and its children (if any) will be traversed.
1152     */
1153    public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1154
1155    /**
1156     * The view is not important for autofill, and its children (if any) will be traversed.
1157     */
1158    public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1159
1160    /**
1161     * The view is important for autofill, but its children (if any) will not be traversed.
1162     */
1163    public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1164
1165    /**
1166     * The view is not important for autofill, and its children (if any) will not be traversed.
1167     */
1168    public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1169
1170    /**
1171     * This view is enabled. Interpretation varies by subclass.
1172     * Use with ENABLED_MASK when calling setFlags.
1173     * {@hide}
1174     */
1175    static final int ENABLED = 0x00000000;
1176
1177    /**
1178     * This view is disabled. Interpretation varies by subclass.
1179     * Use with ENABLED_MASK when calling setFlags.
1180     * {@hide}
1181     */
1182    static final int DISABLED = 0x00000020;
1183
1184   /**
1185    * Mask for use with setFlags indicating bits used for indicating whether
1186    * this view is enabled
1187    * {@hide}
1188    */
1189    static final int ENABLED_MASK = 0x00000020;
1190
1191    /**
1192     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1193     * called and further optimizations will be performed. It is okay to have
1194     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1195     * {@hide}
1196     */
1197    static final int WILL_NOT_DRAW = 0x00000080;
1198
1199    /**
1200     * Mask for use with setFlags indicating bits used for indicating whether
1201     * this view is will draw
1202     * {@hide}
1203     */
1204    static final int DRAW_MASK = 0x00000080;
1205
1206    /**
1207     * <p>This view doesn't show scrollbars.</p>
1208     * {@hide}
1209     */
1210    static final int SCROLLBARS_NONE = 0x00000000;
1211
1212    /**
1213     * <p>This view shows horizontal scrollbars.</p>
1214     * {@hide}
1215     */
1216    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1217
1218    /**
1219     * <p>This view shows vertical scrollbars.</p>
1220     * {@hide}
1221     */
1222    static final int SCROLLBARS_VERTICAL = 0x00000200;
1223
1224    /**
1225     * <p>Mask for use with setFlags indicating bits used for indicating which
1226     * scrollbars are enabled.</p>
1227     * {@hide}
1228     */
1229    static final int SCROLLBARS_MASK = 0x00000300;
1230
1231    /**
1232     * Indicates that the view should filter touches when its window is obscured.
1233     * Refer to the class comments for more information about this security feature.
1234     * {@hide}
1235     */
1236    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1237
1238    /**
1239     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1240     * that they are optional and should be skipped if the window has
1241     * requested system UI flags that ignore those insets for layout.
1242     */
1243    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1244
1245    /**
1246     * <p>This view doesn't show fading edges.</p>
1247     * {@hide}
1248     */
1249    static final int FADING_EDGE_NONE = 0x00000000;
1250
1251    /**
1252     * <p>This view shows horizontal fading edges.</p>
1253     * {@hide}
1254     */
1255    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1256
1257    /**
1258     * <p>This view shows vertical fading edges.</p>
1259     * {@hide}
1260     */
1261    static final int FADING_EDGE_VERTICAL = 0x00002000;
1262
1263    /**
1264     * <p>Mask for use with setFlags indicating bits used for indicating which
1265     * fading edges are enabled.</p>
1266     * {@hide}
1267     */
1268    static final int FADING_EDGE_MASK = 0x00003000;
1269
1270    /**
1271     * <p>Indicates this view can be clicked. When clickable, a View reacts
1272     * to clicks by notifying the OnClickListener.<p>
1273     * {@hide}
1274     */
1275    static final int CLICKABLE = 0x00004000;
1276
1277    /**
1278     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1279     * {@hide}
1280     */
1281    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1282
1283    /**
1284     * <p>Indicates that no icicle should be saved for this view.<p>
1285     * {@hide}
1286     */
1287    static final int SAVE_DISABLED = 0x000010000;
1288
1289    /**
1290     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1291     * property.</p>
1292     * {@hide}
1293     */
1294    static final int SAVE_DISABLED_MASK = 0x000010000;
1295
1296    /**
1297     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1298     * {@hide}
1299     */
1300    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1301
1302    /**
1303     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1304     * {@hide}
1305     */
1306    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1307
1308    /** @hide */
1309    @Retention(RetentionPolicy.SOURCE)
1310    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1311    public @interface DrawingCacheQuality {}
1312
1313    /**
1314     * <p>Enables low quality mode for the drawing cache.</p>
1315     */
1316    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1317
1318    /**
1319     * <p>Enables high quality mode for the drawing cache.</p>
1320     */
1321    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1322
1323    /**
1324     * <p>Enables automatic quality mode for the drawing cache.</p>
1325     */
1326    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1327
1328    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1329            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1330    };
1331
1332    /**
1333     * <p>Mask for use with setFlags indicating bits used for the cache
1334     * quality property.</p>
1335     * {@hide}
1336     */
1337    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1338
1339    /**
1340     * <p>
1341     * Indicates this view can be long clicked. When long clickable, a View
1342     * reacts to long clicks by notifying the OnLongClickListener or showing a
1343     * context menu.
1344     * </p>
1345     * {@hide}
1346     */
1347    static final int LONG_CLICKABLE = 0x00200000;
1348
1349    /**
1350     * <p>Indicates that this view gets its drawable states from its direct parent
1351     * and ignores its original internal states.</p>
1352     *
1353     * @hide
1354     */
1355    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1356
1357    /**
1358     * <p>
1359     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1360     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1361     * OnContextClickListener.
1362     * </p>
1363     * {@hide}
1364     */
1365    static final int CONTEXT_CLICKABLE = 0x00800000;
1366
1367
1368    /** @hide */
1369    @IntDef({
1370        SCROLLBARS_INSIDE_OVERLAY,
1371        SCROLLBARS_INSIDE_INSET,
1372        SCROLLBARS_OUTSIDE_OVERLAY,
1373        SCROLLBARS_OUTSIDE_INSET
1374    })
1375    @Retention(RetentionPolicy.SOURCE)
1376    public @interface ScrollBarStyle {}
1377
1378    /**
1379     * The scrollbar style to display the scrollbars inside the content area,
1380     * without increasing the padding. The scrollbars will be overlaid with
1381     * translucency on the view's content.
1382     */
1383    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1384
1385    /**
1386     * The scrollbar style to display the scrollbars inside the padded area,
1387     * increasing the padding of the view. The scrollbars will not overlap the
1388     * content area of the view.
1389     */
1390    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1391
1392    /**
1393     * The scrollbar style to display the scrollbars at the edge of the view,
1394     * without increasing the padding. The scrollbars will be overlaid with
1395     * translucency.
1396     */
1397    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1398
1399    /**
1400     * The scrollbar style to display the scrollbars at the edge of the view,
1401     * increasing the padding of the view. The scrollbars will only overlap the
1402     * background, if any.
1403     */
1404    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1405
1406    /**
1407     * Mask to check if the scrollbar style is overlay or inset.
1408     * {@hide}
1409     */
1410    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1411
1412    /**
1413     * Mask to check if the scrollbar style is inside or outside.
1414     * {@hide}
1415     */
1416    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1417
1418    /**
1419     * Mask for scrollbar style.
1420     * {@hide}
1421     */
1422    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1423
1424    /**
1425     * View flag indicating that the screen should remain on while the
1426     * window containing this view is visible to the user.  This effectively
1427     * takes care of automatically setting the WindowManager's
1428     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1429     */
1430    public static final int KEEP_SCREEN_ON = 0x04000000;
1431
1432    /**
1433     * View flag indicating whether this view should have sound effects enabled
1434     * for events such as clicking and touching.
1435     */
1436    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1437
1438    /**
1439     * View flag indicating whether this view should have haptic feedback
1440     * enabled for events such as long presses.
1441     */
1442    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1443
1444    /**
1445     * <p>Indicates that the view hierarchy should stop saving state when
1446     * it reaches this view.  If state saving is initiated immediately at
1447     * the view, it will be allowed.
1448     * {@hide}
1449     */
1450    static final int PARENT_SAVE_DISABLED = 0x20000000;
1451
1452    /**
1453     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1454     * {@hide}
1455     */
1456    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1457
1458    private static Paint sDebugPaint;
1459
1460    /**
1461     * <p>Indicates this view can display a tooltip on hover or long press.</p>
1462     * {@hide}
1463     */
1464    static final int TOOLTIP = 0x40000000;
1465
1466    /** @hide */
1467    @IntDef(flag = true,
1468            value = {
1469                FOCUSABLES_ALL,
1470                FOCUSABLES_TOUCH_MODE
1471            })
1472    @Retention(RetentionPolicy.SOURCE)
1473    public @interface FocusableMode {}
1474
1475    /**
1476     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1477     * should add all focusable Views regardless if they are focusable in touch mode.
1478     */
1479    public static final int FOCUSABLES_ALL = 0x00000000;
1480
1481    /**
1482     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1483     * should add only Views focusable in touch mode.
1484     */
1485    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1486
1487    /** @hide */
1488    @IntDef({
1489            FOCUS_BACKWARD,
1490            FOCUS_FORWARD,
1491            FOCUS_LEFT,
1492            FOCUS_UP,
1493            FOCUS_RIGHT,
1494            FOCUS_DOWN
1495    })
1496    @Retention(RetentionPolicy.SOURCE)
1497    public @interface FocusDirection {}
1498
1499    /** @hide */
1500    @IntDef({
1501            FOCUS_LEFT,
1502            FOCUS_UP,
1503            FOCUS_RIGHT,
1504            FOCUS_DOWN
1505    })
1506    @Retention(RetentionPolicy.SOURCE)
1507    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1508
1509    /**
1510     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1511     * item.
1512     */
1513    public static final int FOCUS_BACKWARD = 0x00000001;
1514
1515    /**
1516     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1517     * item.
1518     */
1519    public static final int FOCUS_FORWARD = 0x00000002;
1520
1521    /**
1522     * Use with {@link #focusSearch(int)}. Move focus to the left.
1523     */
1524    public static final int FOCUS_LEFT = 0x00000011;
1525
1526    /**
1527     * Use with {@link #focusSearch(int)}. Move focus up.
1528     */
1529    public static final int FOCUS_UP = 0x00000021;
1530
1531    /**
1532     * Use with {@link #focusSearch(int)}. Move focus to the right.
1533     */
1534    public static final int FOCUS_RIGHT = 0x00000042;
1535
1536    /**
1537     * Use with {@link #focusSearch(int)}. Move focus down.
1538     */
1539    public static final int FOCUS_DOWN = 0x00000082;
1540
1541    /**
1542     * Bits of {@link #getMeasuredWidthAndState()} and
1543     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1544     */
1545    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1546
1547    /**
1548     * Bits of {@link #getMeasuredWidthAndState()} and
1549     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1550     */
1551    public static final int MEASURED_STATE_MASK = 0xff000000;
1552
1553    /**
1554     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1555     * for functions that combine both width and height into a single int,
1556     * such as {@link #getMeasuredState()} and the childState argument of
1557     * {@link #resolveSizeAndState(int, int, int)}.
1558     */
1559    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1560
1561    /**
1562     * Bit of {@link #getMeasuredWidthAndState()} and
1563     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1564     * is smaller that the space the view would like to have.
1565     */
1566    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1567
1568    /**
1569     * Base View state sets
1570     */
1571    // Singles
1572    /**
1573     * Indicates the view has no states set. States are used with
1574     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1575     * view depending on its state.
1576     *
1577     * @see android.graphics.drawable.Drawable
1578     * @see #getDrawableState()
1579     */
1580    protected static final int[] EMPTY_STATE_SET;
1581    /**
1582     * Indicates the view is enabled. States are used with
1583     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1584     * view depending on its state.
1585     *
1586     * @see android.graphics.drawable.Drawable
1587     * @see #getDrawableState()
1588     */
1589    protected static final int[] ENABLED_STATE_SET;
1590    /**
1591     * Indicates the view is focused. States are used with
1592     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1593     * view depending on its state.
1594     *
1595     * @see android.graphics.drawable.Drawable
1596     * @see #getDrawableState()
1597     */
1598    protected static final int[] FOCUSED_STATE_SET;
1599    /**
1600     * Indicates the view is selected. States are used with
1601     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1602     * view depending on its state.
1603     *
1604     * @see android.graphics.drawable.Drawable
1605     * @see #getDrawableState()
1606     */
1607    protected static final int[] SELECTED_STATE_SET;
1608    /**
1609     * Indicates the view is pressed. States are used with
1610     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1611     * view depending on its state.
1612     *
1613     * @see android.graphics.drawable.Drawable
1614     * @see #getDrawableState()
1615     */
1616    protected static final int[] PRESSED_STATE_SET;
1617    /**
1618     * Indicates the view's window has focus. States are used with
1619     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1620     * view depending on its state.
1621     *
1622     * @see android.graphics.drawable.Drawable
1623     * @see #getDrawableState()
1624     */
1625    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1626    // Doubles
1627    /**
1628     * Indicates the view is enabled and has the focus.
1629     *
1630     * @see #ENABLED_STATE_SET
1631     * @see #FOCUSED_STATE_SET
1632     */
1633    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1634    /**
1635     * Indicates the view is enabled and selected.
1636     *
1637     * @see #ENABLED_STATE_SET
1638     * @see #SELECTED_STATE_SET
1639     */
1640    protected static final int[] ENABLED_SELECTED_STATE_SET;
1641    /**
1642     * Indicates the view is enabled and that its window has focus.
1643     *
1644     * @see #ENABLED_STATE_SET
1645     * @see #WINDOW_FOCUSED_STATE_SET
1646     */
1647    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1648    /**
1649     * Indicates the view is focused and selected.
1650     *
1651     * @see #FOCUSED_STATE_SET
1652     * @see #SELECTED_STATE_SET
1653     */
1654    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1655    /**
1656     * Indicates the view has the focus and that its window has the focus.
1657     *
1658     * @see #FOCUSED_STATE_SET
1659     * @see #WINDOW_FOCUSED_STATE_SET
1660     */
1661    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1662    /**
1663     * Indicates the view is selected and that its window has the focus.
1664     *
1665     * @see #SELECTED_STATE_SET
1666     * @see #WINDOW_FOCUSED_STATE_SET
1667     */
1668    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1669    // Triples
1670    /**
1671     * Indicates the view is enabled, focused and selected.
1672     *
1673     * @see #ENABLED_STATE_SET
1674     * @see #FOCUSED_STATE_SET
1675     * @see #SELECTED_STATE_SET
1676     */
1677    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1678    /**
1679     * Indicates the view is enabled, focused and its window has the focus.
1680     *
1681     * @see #ENABLED_STATE_SET
1682     * @see #FOCUSED_STATE_SET
1683     * @see #WINDOW_FOCUSED_STATE_SET
1684     */
1685    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1686    /**
1687     * Indicates the view is enabled, selected and its window has the focus.
1688     *
1689     * @see #ENABLED_STATE_SET
1690     * @see #SELECTED_STATE_SET
1691     * @see #WINDOW_FOCUSED_STATE_SET
1692     */
1693    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1694    /**
1695     * Indicates the view is focused, selected and its window has the focus.
1696     *
1697     * @see #FOCUSED_STATE_SET
1698     * @see #SELECTED_STATE_SET
1699     * @see #WINDOW_FOCUSED_STATE_SET
1700     */
1701    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1702    /**
1703     * Indicates the view is enabled, focused, selected and its window
1704     * has the focus.
1705     *
1706     * @see #ENABLED_STATE_SET
1707     * @see #FOCUSED_STATE_SET
1708     * @see #SELECTED_STATE_SET
1709     * @see #WINDOW_FOCUSED_STATE_SET
1710     */
1711    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1712    /**
1713     * Indicates the view is pressed and its window has the focus.
1714     *
1715     * @see #PRESSED_STATE_SET
1716     * @see #WINDOW_FOCUSED_STATE_SET
1717     */
1718    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1719    /**
1720     * Indicates the view is pressed and selected.
1721     *
1722     * @see #PRESSED_STATE_SET
1723     * @see #SELECTED_STATE_SET
1724     */
1725    protected static final int[] PRESSED_SELECTED_STATE_SET;
1726    /**
1727     * Indicates the view is pressed, selected and its window has the focus.
1728     *
1729     * @see #PRESSED_STATE_SET
1730     * @see #SELECTED_STATE_SET
1731     * @see #WINDOW_FOCUSED_STATE_SET
1732     */
1733    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1734    /**
1735     * Indicates the view is pressed and focused.
1736     *
1737     * @see #PRESSED_STATE_SET
1738     * @see #FOCUSED_STATE_SET
1739     */
1740    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1741    /**
1742     * Indicates the view is pressed, focused and its window has the focus.
1743     *
1744     * @see #PRESSED_STATE_SET
1745     * @see #FOCUSED_STATE_SET
1746     * @see #WINDOW_FOCUSED_STATE_SET
1747     */
1748    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1749    /**
1750     * Indicates the view is pressed, focused and selected.
1751     *
1752     * @see #PRESSED_STATE_SET
1753     * @see #SELECTED_STATE_SET
1754     * @see #FOCUSED_STATE_SET
1755     */
1756    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1757    /**
1758     * Indicates the view is pressed, focused, selected and its window has the focus.
1759     *
1760     * @see #PRESSED_STATE_SET
1761     * @see #FOCUSED_STATE_SET
1762     * @see #SELECTED_STATE_SET
1763     * @see #WINDOW_FOCUSED_STATE_SET
1764     */
1765    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1766    /**
1767     * Indicates the view is pressed and enabled.
1768     *
1769     * @see #PRESSED_STATE_SET
1770     * @see #ENABLED_STATE_SET
1771     */
1772    protected static final int[] PRESSED_ENABLED_STATE_SET;
1773    /**
1774     * Indicates the view is pressed, enabled and its window has the focus.
1775     *
1776     * @see #PRESSED_STATE_SET
1777     * @see #ENABLED_STATE_SET
1778     * @see #WINDOW_FOCUSED_STATE_SET
1779     */
1780    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1781    /**
1782     * Indicates the view is pressed, enabled and selected.
1783     *
1784     * @see #PRESSED_STATE_SET
1785     * @see #ENABLED_STATE_SET
1786     * @see #SELECTED_STATE_SET
1787     */
1788    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1789    /**
1790     * Indicates the view is pressed, enabled, selected and its window has the
1791     * focus.
1792     *
1793     * @see #PRESSED_STATE_SET
1794     * @see #ENABLED_STATE_SET
1795     * @see #SELECTED_STATE_SET
1796     * @see #WINDOW_FOCUSED_STATE_SET
1797     */
1798    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1799    /**
1800     * Indicates the view is pressed, enabled and focused.
1801     *
1802     * @see #PRESSED_STATE_SET
1803     * @see #ENABLED_STATE_SET
1804     * @see #FOCUSED_STATE_SET
1805     */
1806    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1807    /**
1808     * Indicates the view is pressed, enabled, focused and its window has the
1809     * focus.
1810     *
1811     * @see #PRESSED_STATE_SET
1812     * @see #ENABLED_STATE_SET
1813     * @see #FOCUSED_STATE_SET
1814     * @see #WINDOW_FOCUSED_STATE_SET
1815     */
1816    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1817    /**
1818     * Indicates the view is pressed, enabled, focused and selected.
1819     *
1820     * @see #PRESSED_STATE_SET
1821     * @see #ENABLED_STATE_SET
1822     * @see #SELECTED_STATE_SET
1823     * @see #FOCUSED_STATE_SET
1824     */
1825    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1826    /**
1827     * Indicates the view is pressed, enabled, focused, selected and its window
1828     * has the focus.
1829     *
1830     * @see #PRESSED_STATE_SET
1831     * @see #ENABLED_STATE_SET
1832     * @see #SELECTED_STATE_SET
1833     * @see #FOCUSED_STATE_SET
1834     * @see #WINDOW_FOCUSED_STATE_SET
1835     */
1836    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1837
1838    static {
1839        EMPTY_STATE_SET = StateSet.get(0);
1840
1841        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1842
1843        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1844        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1845                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1846
1847        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1848        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1849                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1850        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1851                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1852        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1853                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1854                        | StateSet.VIEW_STATE_FOCUSED);
1855
1856        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1857        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1858                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1859        ENABLED_SELECTED_STATE_SET = StateSet.get(
1860                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1861        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1862                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1863                        | StateSet.VIEW_STATE_ENABLED);
1864        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1865                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1866        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1867                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1868                        | StateSet.VIEW_STATE_ENABLED);
1869        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1870                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1871                        | StateSet.VIEW_STATE_ENABLED);
1872        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1873                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1874                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1875
1876        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1877        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1878                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1879        PRESSED_SELECTED_STATE_SET = StateSet.get(
1880                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1881        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1882                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1883                        | StateSet.VIEW_STATE_PRESSED);
1884        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1885                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1886        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1887                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1888                        | StateSet.VIEW_STATE_PRESSED);
1889        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1890                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1891                        | StateSet.VIEW_STATE_PRESSED);
1892        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1893                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1894                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1895        PRESSED_ENABLED_STATE_SET = StateSet.get(
1896                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1897        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1898                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1899                        | StateSet.VIEW_STATE_PRESSED);
1900        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1901                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1902                        | StateSet.VIEW_STATE_PRESSED);
1903        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1904                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1905                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1906        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1907                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1908                        | StateSet.VIEW_STATE_PRESSED);
1909        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1910                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1911                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1912        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1913                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1914                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1915        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1916                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1917                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1918                        | StateSet.VIEW_STATE_PRESSED);
1919    }
1920
1921    /**
1922     * Accessibility event types that are dispatched for text population.
1923     */
1924    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1925            AccessibilityEvent.TYPE_VIEW_CLICKED
1926            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1927            | AccessibilityEvent.TYPE_VIEW_SELECTED
1928            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1929            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1930            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1931            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1932            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1933            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1934            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1935            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1936
1937    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
1938
1939    static final int DEBUG_CORNERS_SIZE_DIP = 8;
1940
1941    /**
1942     * Temporary Rect currently for use in setBackground().  This will probably
1943     * be extended in the future to hold our own class with more than just
1944     * a Rect. :)
1945     */
1946    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1947
1948    /**
1949     * Map used to store views' tags.
1950     */
1951    private SparseArray<Object> mKeyedTags;
1952
1953    /**
1954     * The animation currently associated with this view.
1955     * @hide
1956     */
1957    protected Animation mCurrentAnimation = null;
1958
1959    /**
1960     * Width as measured during measure pass.
1961     * {@hide}
1962     */
1963    @ViewDebug.ExportedProperty(category = "measurement")
1964    int mMeasuredWidth;
1965
1966    /**
1967     * Height as measured during measure pass.
1968     * {@hide}
1969     */
1970    @ViewDebug.ExportedProperty(category = "measurement")
1971    int mMeasuredHeight;
1972
1973    /**
1974     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1975     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1976     * its display list. This flag, used only when hw accelerated, allows us to clear the
1977     * flag while retaining this information until it's needed (at getDisplayList() time and
1978     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1979     *
1980     * {@hide}
1981     */
1982    boolean mRecreateDisplayList = false;
1983
1984    /**
1985     * The view's identifier.
1986     * {@hide}
1987     *
1988     * @see #setId(int)
1989     * @see #getId()
1990     */
1991    @IdRes
1992    @ViewDebug.ExportedProperty(resolveId = true)
1993    int mID = NO_ID;
1994
1995    /** The ID of this view for accessibility and autofill purposes.
1996     * <ul>
1997     *     <li>== {@link #NO_ID}: ID has not been assigned yet
1998     *     <li>&le; {@link #LAST_APP_ACCESSIBILITY_ID}: View is not part of a activity. The ID is
1999     *                                                  unique in the process. This might change
2000     *                                                  over activity lifecycle events.
2001     *     <li>&gt; {@link #LAST_APP_ACCESSIBILITY_ID}: View is part of a activity. The ID is
2002     *                                                  unique in the activity. This stays the same
2003     *                                                  over activity lifecycle events.
2004     */
2005    private int mAccessibilityViewId = NO_ID;
2006
2007    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2008
2009    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
2010
2011    /**
2012     * The view's tag.
2013     * {@hide}
2014     *
2015     * @see #setTag(Object)
2016     * @see #getTag()
2017     */
2018    protected Object mTag = null;
2019
2020    // for mPrivateFlags:
2021    /** {@hide} */
2022    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2023    /** {@hide} */
2024    static final int PFLAG_FOCUSED                     = 0x00000002;
2025    /** {@hide} */
2026    static final int PFLAG_SELECTED                    = 0x00000004;
2027    /** {@hide} */
2028    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2029    /** {@hide} */
2030    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2031    /** {@hide} */
2032    static final int PFLAG_DRAWN                       = 0x00000020;
2033    /**
2034     * When this flag is set, this view is running an animation on behalf of its
2035     * children and should therefore not cancel invalidate requests, even if they
2036     * lie outside of this view's bounds.
2037     *
2038     * {@hide}
2039     */
2040    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2041    /** {@hide} */
2042    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2043    /** {@hide} */
2044    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2045    /** {@hide} */
2046    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2047    /** {@hide} */
2048    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2049    /** {@hide} */
2050    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2051    /** {@hide} */
2052    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2053
2054    private static final int PFLAG_PRESSED             = 0x00004000;
2055
2056    /** {@hide} */
2057    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2058    /**
2059     * Flag used to indicate that this view should be drawn once more (and only once
2060     * more) after its animation has completed.
2061     * {@hide}
2062     */
2063    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2064
2065    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2066
2067    /**
2068     * Indicates that the View returned true when onSetAlpha() was called and that
2069     * the alpha must be restored.
2070     * {@hide}
2071     */
2072    static final int PFLAG_ALPHA_SET                   = 0x00040000;
2073
2074    /**
2075     * Set by {@link #setScrollContainer(boolean)}.
2076     */
2077    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2078
2079    /**
2080     * Set by {@link #setScrollContainer(boolean)}.
2081     */
2082    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2083
2084    /**
2085     * View flag indicating whether this view was invalidated (fully or partially.)
2086     *
2087     * @hide
2088     */
2089    static final int PFLAG_DIRTY                       = 0x00200000;
2090
2091    /**
2092     * View flag indicating whether this view was invalidated by an opaque
2093     * invalidate request.
2094     *
2095     * @hide
2096     */
2097    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2098
2099    /**
2100     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2101     *
2102     * @hide
2103     */
2104    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2105
2106    /**
2107     * Indicates whether the background is opaque.
2108     *
2109     * @hide
2110     */
2111    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2112
2113    /**
2114     * Indicates whether the scrollbars are opaque.
2115     *
2116     * @hide
2117     */
2118    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2119
2120    /**
2121     * Indicates whether the view is opaque.
2122     *
2123     * @hide
2124     */
2125    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2126
2127    /**
2128     * Indicates a prepressed state;
2129     * the short time between ACTION_DOWN and recognizing
2130     * a 'real' press. Prepressed is used to recognize quick taps
2131     * even when they are shorter than ViewConfiguration.getTapTimeout().
2132     *
2133     * @hide
2134     */
2135    private static final int PFLAG_PREPRESSED          = 0x02000000;
2136
2137    /**
2138     * Indicates whether the view is temporarily detached.
2139     *
2140     * @hide
2141     */
2142    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2143
2144    /**
2145     * Indicates that we should awaken scroll bars once attached
2146     *
2147     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2148     * during window attachment and it is no longer needed. Feel free to repurpose it.
2149     *
2150     * @hide
2151     */
2152    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2153
2154    /**
2155     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2156     * @hide
2157     */
2158    private static final int PFLAG_HOVERED             = 0x10000000;
2159
2160    /**
2161     * no longer needed, should be reused
2162     */
2163    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
2164
2165    /** {@hide} */
2166    static final int PFLAG_ACTIVATED                   = 0x40000000;
2167
2168    /**
2169     * Indicates that this view was specifically invalidated, not just dirtied because some
2170     * child view was invalidated. The flag is used to determine when we need to recreate
2171     * a view's display list (as opposed to just returning a reference to its existing
2172     * display list).
2173     *
2174     * @hide
2175     */
2176    static final int PFLAG_INVALIDATED                 = 0x80000000;
2177
2178    /**
2179     * Masks for mPrivateFlags2, as generated by dumpFlags():
2180     *
2181     * |-------|-------|-------|-------|
2182     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2183     *                                1  PFLAG2_DRAG_HOVERED
2184     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2185     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2186     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2187     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2188     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2189     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2190     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2191     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2192     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2193     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2194     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2195     *                         111       PFLAG2_TEXT_DIRECTION_MASK
2196     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2197     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2198     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2199     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2200     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2201     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2202     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2203     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2204     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2205     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2206     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2207     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2208     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2209     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2210     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2211     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2212     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2213     *     1                             PFLAG2_VIEW_QUICK_REJECTED
2214     *    1                              PFLAG2_PADDING_RESOLVED
2215     *   1                               PFLAG2_DRAWABLE_RESOLVED
2216     *  1                                PFLAG2_HAS_TRANSIENT_STATE
2217     * |-------|-------|-------|-------|
2218     */
2219
2220    /**
2221     * Indicates that this view has reported that it can accept the current drag's content.
2222     * Cleared when the drag operation concludes.
2223     * @hide
2224     */
2225    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2226
2227    /**
2228     * Indicates that this view is currently directly under the drag location in a
2229     * drag-and-drop operation involving content that it can accept.  Cleared when
2230     * the drag exits the view, or when the drag operation concludes.
2231     * @hide
2232     */
2233    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2234
2235    /** @hide */
2236    @IntDef({
2237        LAYOUT_DIRECTION_LTR,
2238        LAYOUT_DIRECTION_RTL,
2239        LAYOUT_DIRECTION_INHERIT,
2240        LAYOUT_DIRECTION_LOCALE
2241    })
2242    @Retention(RetentionPolicy.SOURCE)
2243    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2244    public @interface LayoutDir {}
2245
2246    /** @hide */
2247    @IntDef({
2248        LAYOUT_DIRECTION_LTR,
2249        LAYOUT_DIRECTION_RTL
2250    })
2251    @Retention(RetentionPolicy.SOURCE)
2252    public @interface ResolvedLayoutDir {}
2253
2254    /**
2255     * A flag to indicate that the layout direction of this view has not been defined yet.
2256     * @hide
2257     */
2258    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2259
2260    /**
2261     * Horizontal layout direction of this view is from Left to Right.
2262     * Use with {@link #setLayoutDirection}.
2263     */
2264    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2265
2266    /**
2267     * Horizontal layout direction of this view is from Right to Left.
2268     * Use with {@link #setLayoutDirection}.
2269     */
2270    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2271
2272    /**
2273     * Horizontal layout direction of this view is inherited from its parent.
2274     * Use with {@link #setLayoutDirection}.
2275     */
2276    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2277
2278    /**
2279     * Horizontal layout direction of this view is from deduced from the default language
2280     * script for the locale. Use with {@link #setLayoutDirection}.
2281     */
2282    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2283
2284    /**
2285     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2286     * @hide
2287     */
2288    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2289
2290    /**
2291     * Mask for use with private flags indicating bits used for horizontal layout direction.
2292     * @hide
2293     */
2294    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2295
2296    /**
2297     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2298     * right-to-left direction.
2299     * @hide
2300     */
2301    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2302
2303    /**
2304     * Indicates whether the view horizontal layout direction has been resolved.
2305     * @hide
2306     */
2307    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2308
2309    /**
2310     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2311     * @hide
2312     */
2313    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2314            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2315
2316    /*
2317     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2318     * flag value.
2319     * @hide
2320     */
2321    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2322            LAYOUT_DIRECTION_LTR,
2323            LAYOUT_DIRECTION_RTL,
2324            LAYOUT_DIRECTION_INHERIT,
2325            LAYOUT_DIRECTION_LOCALE
2326    };
2327
2328    /**
2329     * Default horizontal layout direction.
2330     */
2331    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2332
2333    /**
2334     * Default horizontal layout direction.
2335     * @hide
2336     */
2337    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2338
2339    /**
2340     * Text direction is inherited through {@link ViewGroup}
2341     */
2342    public static final int TEXT_DIRECTION_INHERIT = 0;
2343
2344    /**
2345     * Text direction is using "first strong algorithm". The first strong directional character
2346     * determines the paragraph direction. If there is no strong directional character, the
2347     * paragraph direction is the view's resolved layout direction.
2348     */
2349    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2350
2351    /**
2352     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2353     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2354     * If there are neither, the paragraph direction is the view's resolved layout direction.
2355     */
2356    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2357
2358    /**
2359     * Text direction is forced to LTR.
2360     */
2361    public static final int TEXT_DIRECTION_LTR = 3;
2362
2363    /**
2364     * Text direction is forced to RTL.
2365     */
2366    public static final int TEXT_DIRECTION_RTL = 4;
2367
2368    /**
2369     * Text direction is coming from the system Locale.
2370     */
2371    public static final int TEXT_DIRECTION_LOCALE = 5;
2372
2373    /**
2374     * Text direction is using "first strong algorithm". The first strong directional character
2375     * determines the paragraph direction. If there is no strong directional character, the
2376     * paragraph direction is LTR.
2377     */
2378    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2379
2380    /**
2381     * Text direction is using "first strong algorithm". The first strong directional character
2382     * determines the paragraph direction. If there is no strong directional character, the
2383     * paragraph direction is RTL.
2384     */
2385    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2386
2387    /**
2388     * Default text direction is inherited
2389     */
2390    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2391
2392    /**
2393     * Default resolved text direction
2394     * @hide
2395     */
2396    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2397
2398    /**
2399     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2400     * @hide
2401     */
2402    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2403
2404    /**
2405     * Mask for use with private flags indicating bits used for text direction.
2406     * @hide
2407     */
2408    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2409            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2410
2411    /**
2412     * Array of text direction flags for mapping attribute "textDirection" to correct
2413     * flag value.
2414     * @hide
2415     */
2416    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2417            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2418            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2419            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2420            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2421            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2422            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2423            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2424            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2425    };
2426
2427    /**
2428     * Indicates whether the view text direction has been resolved.
2429     * @hide
2430     */
2431    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2432            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2433
2434    /**
2435     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2436     * @hide
2437     */
2438    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2439
2440    /**
2441     * Mask for use with private flags indicating bits used for resolved text direction.
2442     * @hide
2443     */
2444    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2445            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2446
2447    /**
2448     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2449     * @hide
2450     */
2451    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2452            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2453
2454    /** @hide */
2455    @IntDef({
2456        TEXT_ALIGNMENT_INHERIT,
2457        TEXT_ALIGNMENT_GRAVITY,
2458        TEXT_ALIGNMENT_CENTER,
2459        TEXT_ALIGNMENT_TEXT_START,
2460        TEXT_ALIGNMENT_TEXT_END,
2461        TEXT_ALIGNMENT_VIEW_START,
2462        TEXT_ALIGNMENT_VIEW_END
2463    })
2464    @Retention(RetentionPolicy.SOURCE)
2465    public @interface TextAlignment {}
2466
2467    /**
2468     * Default text alignment. The text alignment of this View is inherited from its parent.
2469     * Use with {@link #setTextAlignment(int)}
2470     */
2471    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2472
2473    /**
2474     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2475     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2476     *
2477     * Use with {@link #setTextAlignment(int)}
2478     */
2479    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2480
2481    /**
2482     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2483     *
2484     * Use with {@link #setTextAlignment(int)}
2485     */
2486    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2487
2488    /**
2489     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2490     *
2491     * Use with {@link #setTextAlignment(int)}
2492     */
2493    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2494
2495    /**
2496     * Center the paragraph, e.g. ALIGN_CENTER.
2497     *
2498     * Use with {@link #setTextAlignment(int)}
2499     */
2500    public static final int TEXT_ALIGNMENT_CENTER = 4;
2501
2502    /**
2503     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2504     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2505     *
2506     * Use with {@link #setTextAlignment(int)}
2507     */
2508    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2509
2510    /**
2511     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2512     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2513     *
2514     * Use with {@link #setTextAlignment(int)}
2515     */
2516    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2517
2518    /**
2519     * Default text alignment is inherited
2520     */
2521    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2522
2523    /**
2524     * Default resolved text alignment
2525     * @hide
2526     */
2527    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2528
2529    /**
2530      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2531      * @hide
2532      */
2533    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2534
2535    /**
2536      * Mask for use with private flags indicating bits used for text alignment.
2537      * @hide
2538      */
2539    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2540
2541    /**
2542     * Array of text direction flags for mapping attribute "textAlignment" to correct
2543     * flag value.
2544     * @hide
2545     */
2546    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2547            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2548            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2549            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2550            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2551            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2552            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2553            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2554    };
2555
2556    /**
2557     * Indicates whether the view text alignment has been resolved.
2558     * @hide
2559     */
2560    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2561
2562    /**
2563     * Bit shift to get the resolved text alignment.
2564     * @hide
2565     */
2566    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2567
2568    /**
2569     * Mask for use with private flags indicating bits used for text alignment.
2570     * @hide
2571     */
2572    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2573            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2574
2575    /**
2576     * Indicates whether if the view text alignment has been resolved to gravity
2577     */
2578    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2579            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2580
2581    // Accessiblity constants for mPrivateFlags2
2582
2583    /**
2584     * Shift for the bits in {@link #mPrivateFlags2} related to the
2585     * "importantForAccessibility" attribute.
2586     */
2587    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2588
2589    /**
2590     * Automatically determine whether a view is important for accessibility.
2591     */
2592    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2593
2594    /**
2595     * The view is important for accessibility.
2596     */
2597    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2598
2599    /**
2600     * The view is not important for accessibility.
2601     */
2602    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2603
2604    /**
2605     * The view is not important for accessibility, nor are any of its
2606     * descendant views.
2607     */
2608    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2609
2610    /**
2611     * The default whether the view is important for accessibility.
2612     */
2613    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2614
2615    /**
2616     * Mask for obtaining the bits which specify how to determine
2617     * whether a view is important for accessibility.
2618     */
2619    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2620        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2621        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2622        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2623
2624    /**
2625     * Shift for the bits in {@link #mPrivateFlags2} related to the
2626     * "accessibilityLiveRegion" attribute.
2627     */
2628    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2629
2630    /**
2631     * Live region mode specifying that accessibility services should not
2632     * automatically announce changes to this view. This is the default live
2633     * region mode for most views.
2634     * <p>
2635     * Use with {@link #setAccessibilityLiveRegion(int)}.
2636     */
2637    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2638
2639    /**
2640     * Live region mode specifying that accessibility services should announce
2641     * changes to this view.
2642     * <p>
2643     * Use with {@link #setAccessibilityLiveRegion(int)}.
2644     */
2645    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2646
2647    /**
2648     * Live region mode specifying that accessibility services should interrupt
2649     * ongoing speech to immediately announce changes to this view.
2650     * <p>
2651     * Use with {@link #setAccessibilityLiveRegion(int)}.
2652     */
2653    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2654
2655    /**
2656     * The default whether the view is important for accessibility.
2657     */
2658    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2659
2660    /**
2661     * Mask for obtaining the bits which specify a view's accessibility live
2662     * region mode.
2663     */
2664    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2665            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2666            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2667
2668    /**
2669     * Flag indicating whether a view has accessibility focus.
2670     */
2671    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2672
2673    /**
2674     * Flag whether the accessibility state of the subtree rooted at this view changed.
2675     */
2676    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2677
2678    /**
2679     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2680     * is used to check whether later changes to the view's transform should invalidate the
2681     * view to force the quickReject test to run again.
2682     */
2683    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2684
2685    /**
2686     * Flag indicating that start/end padding has been resolved into left/right padding
2687     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2688     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2689     * during measurement. In some special cases this is required such as when an adapter-based
2690     * view measures prospective children without attaching them to a window.
2691     */
2692    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2693
2694    /**
2695     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2696     */
2697    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2698
2699    /**
2700     * Indicates that the view is tracking some sort of transient state
2701     * that the app should not need to be aware of, but that the framework
2702     * should take special care to preserve.
2703     */
2704    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2705
2706    /**
2707     * Group of bits indicating that RTL properties resolution is done.
2708     */
2709    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2710            PFLAG2_TEXT_DIRECTION_RESOLVED |
2711            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2712            PFLAG2_PADDING_RESOLVED |
2713            PFLAG2_DRAWABLE_RESOLVED;
2714
2715    // There are a couple of flags left in mPrivateFlags2
2716
2717    /* End of masks for mPrivateFlags2 */
2718
2719    /**
2720     * Masks for mPrivateFlags3, as generated by dumpFlags():
2721     *
2722     * |-------|-------|-------|-------|
2723     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2724     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2725     *                               1   PFLAG3_IS_LAID_OUT
2726     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2727     *                             1     PFLAG3_CALLED_SUPER
2728     *                            1      PFLAG3_APPLYING_INSETS
2729     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2730     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2731     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2732     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2733     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2734     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2735     *                     1             PFLAG3_SCROLL_INDICATOR_START
2736     *                    1              PFLAG3_SCROLL_INDICATOR_END
2737     *                   1               PFLAG3_ASSIST_BLOCKED
2738     *                  1                PFLAG3_CLUSTER
2739     *                 1                 PFLAG3_IS_AUTOFILLED
2740     *                1                  PFLAG3_FINGER_DOWN
2741     *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2742     *             __                    unused
2743     *           11                      PFLAG3_IMPORTANT_FOR_AUTOFILL
2744     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2745     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2746     *        1                          PFLAG3_TEMPORARY_DETACH
2747     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2748     * |-------|-------|-------|-------|
2749     */
2750
2751    /**
2752     * Flag indicating that view has a transform animation set on it. This is used to track whether
2753     * an animation is cleared between successive frames, in order to tell the associated
2754     * DisplayList to clear its animation matrix.
2755     */
2756    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2757
2758    /**
2759     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2760     * animation is cleared between successive frames, in order to tell the associated
2761     * DisplayList to restore its alpha value.
2762     */
2763    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2764
2765    /**
2766     * Flag indicating that the view has been through at least one layout since it
2767     * was last attached to a window.
2768     */
2769    static final int PFLAG3_IS_LAID_OUT = 0x4;
2770
2771    /**
2772     * Flag indicating that a call to measure() was skipped and should be done
2773     * instead when layout() is invoked.
2774     */
2775    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2776
2777    /**
2778     * Flag indicating that an overridden method correctly called down to
2779     * the superclass implementation as required by the API spec.
2780     */
2781    static final int PFLAG3_CALLED_SUPER = 0x10;
2782
2783    /**
2784     * Flag indicating that we're in the process of applying window insets.
2785     */
2786    static final int PFLAG3_APPLYING_INSETS = 0x20;
2787
2788    /**
2789     * Flag indicating that we're in the process of fitting system windows using the old method.
2790     */
2791    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2792
2793    /**
2794     * Flag indicating that nested scrolling is enabled for this view.
2795     * The view will optionally cooperate with views up its parent chain to allow for
2796     * integrated nested scrolling along the same axis.
2797     */
2798    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2799
2800    /**
2801     * Flag indicating that the bottom scroll indicator should be displayed
2802     * when this view can scroll up.
2803     */
2804    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2805
2806    /**
2807     * Flag indicating that the bottom scroll indicator should be displayed
2808     * when this view can scroll down.
2809     */
2810    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2811
2812    /**
2813     * Flag indicating that the left scroll indicator should be displayed
2814     * when this view can scroll left.
2815     */
2816    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2817
2818    /**
2819     * Flag indicating that the right scroll indicator should be displayed
2820     * when this view can scroll right.
2821     */
2822    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2823
2824    /**
2825     * Flag indicating that the start scroll indicator should be displayed
2826     * when this view can scroll in the start direction.
2827     */
2828    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2829
2830    /**
2831     * Flag indicating that the end scroll indicator should be displayed
2832     * when this view can scroll in the end direction.
2833     */
2834    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2835
2836    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2837
2838    static final int SCROLL_INDICATORS_NONE = 0x0000;
2839
2840    /**
2841     * Mask for use with setFlags indicating bits used for indicating which
2842     * scroll indicators are enabled.
2843     */
2844    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2845            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2846            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2847            | PFLAG3_SCROLL_INDICATOR_END;
2848
2849    /**
2850     * Left-shift required to translate between public scroll indicator flags
2851     * and internal PFLAGS3 flags. When used as a right-shift, translates
2852     * PFLAGS3 flags to public flags.
2853     */
2854    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2855
2856    /** @hide */
2857    @Retention(RetentionPolicy.SOURCE)
2858    @IntDef(flag = true,
2859            value = {
2860                    SCROLL_INDICATOR_TOP,
2861                    SCROLL_INDICATOR_BOTTOM,
2862                    SCROLL_INDICATOR_LEFT,
2863                    SCROLL_INDICATOR_RIGHT,
2864                    SCROLL_INDICATOR_START,
2865                    SCROLL_INDICATOR_END,
2866            })
2867    public @interface ScrollIndicators {}
2868
2869    /**
2870     * Scroll indicator direction for the top edge of the view.
2871     *
2872     * @see #setScrollIndicators(int)
2873     * @see #setScrollIndicators(int, int)
2874     * @see #getScrollIndicators()
2875     */
2876    public static final int SCROLL_INDICATOR_TOP =
2877            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2878
2879    /**
2880     * Scroll indicator direction for the bottom edge of the view.
2881     *
2882     * @see #setScrollIndicators(int)
2883     * @see #setScrollIndicators(int, int)
2884     * @see #getScrollIndicators()
2885     */
2886    public static final int SCROLL_INDICATOR_BOTTOM =
2887            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2888
2889    /**
2890     * Scroll indicator direction for the left edge of the view.
2891     *
2892     * @see #setScrollIndicators(int)
2893     * @see #setScrollIndicators(int, int)
2894     * @see #getScrollIndicators()
2895     */
2896    public static final int SCROLL_INDICATOR_LEFT =
2897            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2898
2899    /**
2900     * Scroll indicator direction for the right edge of the view.
2901     *
2902     * @see #setScrollIndicators(int)
2903     * @see #setScrollIndicators(int, int)
2904     * @see #getScrollIndicators()
2905     */
2906    public static final int SCROLL_INDICATOR_RIGHT =
2907            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2908
2909    /**
2910     * Scroll indicator direction for the starting edge of the view.
2911     * <p>
2912     * Resolved according to the view's layout direction, see
2913     * {@link #getLayoutDirection()} for more information.
2914     *
2915     * @see #setScrollIndicators(int)
2916     * @see #setScrollIndicators(int, int)
2917     * @see #getScrollIndicators()
2918     */
2919    public static final int SCROLL_INDICATOR_START =
2920            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2921
2922    /**
2923     * Scroll indicator direction for the ending edge of the view.
2924     * <p>
2925     * Resolved according to the view's layout direction, see
2926     * {@link #getLayoutDirection()} for more information.
2927     *
2928     * @see #setScrollIndicators(int)
2929     * @see #setScrollIndicators(int, int)
2930     * @see #getScrollIndicators()
2931     */
2932    public static final int SCROLL_INDICATOR_END =
2933            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2934
2935    /**
2936     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2937     * into this view.<p>
2938     */
2939    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2940
2941    /**
2942     * Flag indicating that the view is a root of a keyboard navigation cluster.
2943     *
2944     * @see #isKeyboardNavigationCluster()
2945     * @see #setKeyboardNavigationCluster(boolean)
2946     */
2947    private static final int PFLAG3_CLUSTER = 0x8000;
2948
2949    /**
2950     * Flag indicating that the view is autofilled
2951     *
2952     * @see #isAutofilled()
2953     * @see #setAutofilled(boolean)
2954     */
2955    private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
2956
2957    /**
2958     * Indicates that the user is currently touching the screen.
2959     * Currently used for the tooltip positioning only.
2960     */
2961    private static final int PFLAG3_FINGER_DOWN = 0x20000;
2962
2963    /**
2964     * Flag indicating that this view is the default-focus view.
2965     *
2966     * @see #isFocusedByDefault()
2967     * @see #setFocusedByDefault(boolean)
2968     */
2969    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
2970
2971    /**
2972     * Shift for the bits in {@link #mPrivateFlags3} related to the
2973     * "importantForAutofill" attribute.
2974     */
2975    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 21;
2976
2977    /**
2978     * Mask for obtaining the bits which specify how to determine
2979     * whether a view is important for autofill.
2980     */
2981    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
2982            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO)
2983            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
2984
2985    /**
2986     * Whether this view has rendered elements that overlap (see {@link
2987     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
2988     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
2989     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
2990     * determined by whatever {@link #hasOverlappingRendering()} returns.
2991     */
2992    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
2993
2994    /**
2995     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
2996     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
2997     */
2998    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
2999
3000    /**
3001     * Flag indicating that the view is temporarily detached from the parent view.
3002     *
3003     * @see #onStartTemporaryDetach()
3004     * @see #onFinishTemporaryDetach()
3005     */
3006    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3007
3008    /**
3009     * Flag indicating that the view does not wish to be revealed within its parent
3010     * hierarchy when it gains focus. Expressed in the negative since the historical
3011     * default behavior is to reveal on focus; this flag suppresses that behavior.
3012     *
3013     * @see #setRevealOnFocusHint(boolean)
3014     * @see #getRevealOnFocusHint()
3015     */
3016    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3017
3018    /* End of masks for mPrivateFlags3 */
3019
3020    /**
3021     * Always allow a user to over-scroll this view, provided it is a
3022     * view that can scroll.
3023     *
3024     * @see #getOverScrollMode()
3025     * @see #setOverScrollMode(int)
3026     */
3027    public static final int OVER_SCROLL_ALWAYS = 0;
3028
3029    /**
3030     * Allow a user to over-scroll this view only if the content is large
3031     * enough to meaningfully scroll, provided it is a view that can scroll.
3032     *
3033     * @see #getOverScrollMode()
3034     * @see #setOverScrollMode(int)
3035     */
3036    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3037
3038    /**
3039     * Never allow a user to over-scroll this view.
3040     *
3041     * @see #getOverScrollMode()
3042     * @see #setOverScrollMode(int)
3043     */
3044    public static final int OVER_SCROLL_NEVER = 2;
3045
3046    /**
3047     * Special constant for {@link #setSystemUiVisibility(int)}: View has
3048     * requested the system UI (status bar) to be visible (the default).
3049     *
3050     * @see #setSystemUiVisibility(int)
3051     */
3052    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3053
3054    /**
3055     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3056     * system UI to enter an unobtrusive "low profile" mode.
3057     *
3058     * <p>This is for use in games, book readers, video players, or any other
3059     * "immersive" application where the usual system chrome is deemed too distracting.
3060     *
3061     * <p>In low profile mode, the status bar and/or navigation icons may dim.
3062     *
3063     * @see #setSystemUiVisibility(int)
3064     */
3065    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3066
3067    /**
3068     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3069     * system navigation be temporarily hidden.
3070     *
3071     * <p>This is an even less obtrusive state than that called for by
3072     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3073     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3074     * those to disappear. This is useful (in conjunction with the
3075     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3076     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3077     * window flags) for displaying content using every last pixel on the display.
3078     *
3079     * <p>There is a limitation: because navigation controls are so important, the least user
3080     * interaction will cause them to reappear immediately.  When this happens, both
3081     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3082     * so that both elements reappear at the same time.
3083     *
3084     * @see #setSystemUiVisibility(int)
3085     */
3086    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3087
3088    /**
3089     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3090     * into the normal fullscreen mode so that its content can take over the screen
3091     * while still allowing the user to interact with the application.
3092     *
3093     * <p>This has the same visual effect as
3094     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3095     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3096     * meaning that non-critical screen decorations (such as the status bar) will be
3097     * hidden while the user is in the View's window, focusing the experience on
3098     * that content.  Unlike the window flag, if you are using ActionBar in
3099     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3100     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3101     * hide the action bar.
3102     *
3103     * <p>This approach to going fullscreen is best used over the window flag when
3104     * it is a transient state -- that is, the application does this at certain
3105     * points in its user interaction where it wants to allow the user to focus
3106     * on content, but not as a continuous state.  For situations where the application
3107     * would like to simply stay full screen the entire time (such as a game that
3108     * wants to take over the screen), the
3109     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3110     * is usually a better approach.  The state set here will be removed by the system
3111     * in various situations (such as the user moving to another application) like
3112     * the other system UI states.
3113     *
3114     * <p>When using this flag, the application should provide some easy facility
3115     * for the user to go out of it.  A common example would be in an e-book
3116     * reader, where tapping on the screen brings back whatever screen and UI
3117     * decorations that had been hidden while the user was immersed in reading
3118     * the book.
3119     *
3120     * @see #setSystemUiVisibility(int)
3121     */
3122    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3123
3124    /**
3125     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3126     * flags, we would like a stable view of the content insets given to
3127     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3128     * will always represent the worst case that the application can expect
3129     * as a continuous state.  In the stock Android UI this is the space for
3130     * the system bar, nav bar, and status bar, but not more transient elements
3131     * such as an input method.
3132     *
3133     * The stable layout your UI sees is based on the system UI modes you can
3134     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3135     * then you will get a stable layout for changes of the
3136     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3137     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3138     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3139     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3140     * with a stable layout.  (Note that you should avoid using
3141     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3142     *
3143     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3144     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3145     * then a hidden status bar will be considered a "stable" state for purposes
3146     * here.  This allows your UI to continually hide the status bar, while still
3147     * using the system UI flags to hide the action bar while still retaining
3148     * a stable layout.  Note that changing the window fullscreen flag will never
3149     * provide a stable layout for a clean transition.
3150     *
3151     * <p>If you are using ActionBar in
3152     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3153     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3154     * insets it adds to those given to the application.
3155     */
3156    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3157
3158    /**
3159     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3160     * to be laid out as if it has requested
3161     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3162     * allows it to avoid artifacts when switching in and out of that mode, at
3163     * the expense that some of its user interface may be covered by screen
3164     * decorations when they are shown.  You can perform layout of your inner
3165     * UI elements to account for the navigation system UI through the
3166     * {@link #fitSystemWindows(Rect)} method.
3167     */
3168    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3169
3170    /**
3171     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3172     * to be laid out as if it has requested
3173     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3174     * allows it to avoid artifacts when switching in and out of that mode, at
3175     * the expense that some of its user interface may be covered by screen
3176     * decorations when they are shown.  You can perform layout of your inner
3177     * UI elements to account for non-fullscreen system UI through the
3178     * {@link #fitSystemWindows(Rect)} method.
3179     */
3180    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3181
3182    /**
3183     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3184     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3185     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3186     * user interaction.
3187     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3188     * has an effect when used in combination with that flag.</p>
3189     */
3190    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3191
3192    /**
3193     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3194     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3195     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3196     * experience while also hiding the system bars.  If this flag is not set,
3197     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3198     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3199     * if the user swipes from the top of the screen.
3200     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3201     * system gestures, such as swiping from the top of the screen.  These transient system bars
3202     * will overlay app’s content, may have some degree of transparency, and will automatically
3203     * hide after a short timeout.
3204     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3205     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3206     * with one or both of those flags.</p>
3207     */
3208    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3209
3210    /**
3211     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3212     * is compatible with light status bar backgrounds.
3213     *
3214     * <p>For this to take effect, the window must request
3215     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3216     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3217     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3218     *         FLAG_TRANSLUCENT_STATUS}.
3219     *
3220     * @see android.R.attr#windowLightStatusBar
3221     */
3222    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3223
3224    /**
3225     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3226     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3227     */
3228    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3229
3230    /**
3231     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3232     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3233     */
3234    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3235
3236    /**
3237     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3238     * that is compatible with light navigation bar backgrounds.
3239     *
3240     * <p>For this to take effect, the window must request
3241     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3242     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3243     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3244     *         FLAG_TRANSLUCENT_NAVIGATION}.
3245     */
3246    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3247
3248    /**
3249     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3250     */
3251    @Deprecated
3252    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3253
3254    /**
3255     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3256     */
3257    @Deprecated
3258    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3259
3260    /**
3261     * @hide
3262     *
3263     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3264     * out of the public fields to keep the undefined bits out of the developer's way.
3265     *
3266     * Flag to make the status bar not expandable.  Unless you also
3267     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3268     */
3269    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3270
3271    /**
3272     * @hide
3273     *
3274     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3275     * out of the public fields to keep the undefined bits out of the developer's way.
3276     *
3277     * Flag to hide notification icons and scrolling ticker text.
3278     */
3279    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3280
3281    /**
3282     * @hide
3283     *
3284     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3285     * out of the public fields to keep the undefined bits out of the developer's way.
3286     *
3287     * Flag to disable incoming notification alerts.  This will not block
3288     * icons, but it will block sound, vibrating and other visual or aural notifications.
3289     */
3290    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3291
3292    /**
3293     * @hide
3294     *
3295     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3296     * out of the public fields to keep the undefined bits out of the developer's way.
3297     *
3298     * Flag to hide only the scrolling ticker.  Note that
3299     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3300     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3301     */
3302    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3303
3304    /**
3305     * @hide
3306     *
3307     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3308     * out of the public fields to keep the undefined bits out of the developer's way.
3309     *
3310     * Flag to hide the center system info area.
3311     */
3312    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3313
3314    /**
3315     * @hide
3316     *
3317     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3318     * out of the public fields to keep the undefined bits out of the developer's way.
3319     *
3320     * Flag to hide only the home button.  Don't use this
3321     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3322     */
3323    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3324
3325    /**
3326     * @hide
3327     *
3328     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3329     * out of the public fields to keep the undefined bits out of the developer's way.
3330     *
3331     * Flag to hide only the back button. Don't use this
3332     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3333     */
3334    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3335
3336    /**
3337     * @hide
3338     *
3339     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3340     * out of the public fields to keep the undefined bits out of the developer's way.
3341     *
3342     * Flag to hide only the clock.  You might use this if your activity has
3343     * its own clock making the status bar's clock redundant.
3344     */
3345    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3346
3347    /**
3348     * @hide
3349     *
3350     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3351     * out of the public fields to keep the undefined bits out of the developer's way.
3352     *
3353     * Flag to hide only the recent apps button. Don't use this
3354     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3355     */
3356    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3357
3358    /**
3359     * @hide
3360     *
3361     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3362     * out of the public fields to keep the undefined bits out of the developer's way.
3363     *
3364     * Flag to disable the global search gesture. Don't use this
3365     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3366     */
3367    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3368
3369    /**
3370     * @hide
3371     *
3372     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3373     * out of the public fields to keep the undefined bits out of the developer's way.
3374     *
3375     * Flag to specify that the status bar is displayed in transient mode.
3376     */
3377    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3378
3379    /**
3380     * @hide
3381     *
3382     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3383     * out of the public fields to keep the undefined bits out of the developer's way.
3384     *
3385     * Flag to specify that the navigation bar is displayed in transient mode.
3386     */
3387    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3388
3389    /**
3390     * @hide
3391     *
3392     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3393     * out of the public fields to keep the undefined bits out of the developer's way.
3394     *
3395     * Flag to specify that the hidden status bar would like to be shown.
3396     */
3397    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3398
3399    /**
3400     * @hide
3401     *
3402     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3403     * out of the public fields to keep the undefined bits out of the developer's way.
3404     *
3405     * Flag to specify that the hidden navigation bar would like to be shown.
3406     */
3407    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3408
3409    /**
3410     * @hide
3411     *
3412     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3413     * out of the public fields to keep the undefined bits out of the developer's way.
3414     *
3415     * Flag to specify that the status bar is displayed in translucent mode.
3416     */
3417    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3418
3419    /**
3420     * @hide
3421     *
3422     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3423     * out of the public fields to keep the undefined bits out of the developer's way.
3424     *
3425     * Flag to specify that the navigation bar is displayed in translucent mode.
3426     */
3427    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3428
3429    /**
3430     * @hide
3431     *
3432     * Makes navigation bar transparent (but not the status bar).
3433     */
3434    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3435
3436    /**
3437     * @hide
3438     *
3439     * Makes status bar transparent (but not the navigation bar).
3440     */
3441    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3442
3443    /**
3444     * @hide
3445     *
3446     * Makes both status bar and navigation bar transparent.
3447     */
3448    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3449            | STATUS_BAR_TRANSPARENT;
3450
3451    /**
3452     * @hide
3453     */
3454    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3455
3456    /**
3457     * These are the system UI flags that can be cleared by events outside
3458     * of an application.  Currently this is just the ability to tap on the
3459     * screen while hiding the navigation bar to have it return.
3460     * @hide
3461     */
3462    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3463            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3464            | SYSTEM_UI_FLAG_FULLSCREEN;
3465
3466    /**
3467     * Flags that can impact the layout in relation to system UI.
3468     */
3469    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3470            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3471            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3472
3473    /** @hide */
3474    @IntDef(flag = true,
3475            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3476    @Retention(RetentionPolicy.SOURCE)
3477    public @interface FindViewFlags {}
3478
3479    /**
3480     * Find views that render the specified text.
3481     *
3482     * @see #findViewsWithText(ArrayList, CharSequence, int)
3483     */
3484    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3485
3486    /**
3487     * Find find views that contain the specified content description.
3488     *
3489     * @see #findViewsWithText(ArrayList, CharSequence, int)
3490     */
3491    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3492
3493    /**
3494     * Find views that contain {@link AccessibilityNodeProvider}. Such
3495     * a View is a root of virtual view hierarchy and may contain the searched
3496     * text. If this flag is set Views with providers are automatically
3497     * added and it is a responsibility of the client to call the APIs of
3498     * the provider to determine whether the virtual tree rooted at this View
3499     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3500     * representing the virtual views with this text.
3501     *
3502     * @see #findViewsWithText(ArrayList, CharSequence, int)
3503     *
3504     * @hide
3505     */
3506    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3507
3508    /**
3509     * The undefined cursor position.
3510     *
3511     * @hide
3512     */
3513    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3514
3515    /**
3516     * Indicates that the screen has changed state and is now off.
3517     *
3518     * @see #onScreenStateChanged(int)
3519     */
3520    public static final int SCREEN_STATE_OFF = 0x0;
3521
3522    /**
3523     * Indicates that the screen has changed state and is now on.
3524     *
3525     * @see #onScreenStateChanged(int)
3526     */
3527    public static final int SCREEN_STATE_ON = 0x1;
3528
3529    /**
3530     * Indicates no axis of view scrolling.
3531     */
3532    public static final int SCROLL_AXIS_NONE = 0;
3533
3534    /**
3535     * Indicates scrolling along the horizontal axis.
3536     */
3537    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3538
3539    /**
3540     * Indicates scrolling along the vertical axis.
3541     */
3542    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3543
3544    /**
3545     * Controls the over-scroll mode for this view.
3546     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3547     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3548     * and {@link #OVER_SCROLL_NEVER}.
3549     */
3550    private int mOverScrollMode;
3551
3552    /**
3553     * The parent this view is attached to.
3554     * {@hide}
3555     *
3556     * @see #getParent()
3557     */
3558    protected ViewParent mParent;
3559
3560    /**
3561     * {@hide}
3562     */
3563    AttachInfo mAttachInfo;
3564
3565    /**
3566     * {@hide}
3567     */
3568    @ViewDebug.ExportedProperty(flagMapping = {
3569        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3570                name = "FORCE_LAYOUT"),
3571        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3572                name = "LAYOUT_REQUIRED"),
3573        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3574            name = "DRAWING_CACHE_INVALID", outputIf = false),
3575        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3576        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3577        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3578        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3579    }, formatToHexString = true)
3580
3581    /* @hide */
3582    public int mPrivateFlags;
3583    int mPrivateFlags2;
3584    int mPrivateFlags3;
3585
3586    /**
3587     * This view's request for the visibility of the status bar.
3588     * @hide
3589     */
3590    @ViewDebug.ExportedProperty(flagMapping = {
3591        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3592                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3593                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3594        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3595                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3596                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3597        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3598                                equals = SYSTEM_UI_FLAG_VISIBLE,
3599                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3600    }, formatToHexString = true)
3601    int mSystemUiVisibility;
3602
3603    /**
3604     * Reference count for transient state.
3605     * @see #setHasTransientState(boolean)
3606     */
3607    int mTransientStateCount = 0;
3608
3609    /**
3610     * Count of how many windows this view has been attached to.
3611     */
3612    int mWindowAttachCount;
3613
3614    /**
3615     * The layout parameters associated with this view and used by the parent
3616     * {@link android.view.ViewGroup} to determine how this view should be
3617     * laid out.
3618     * {@hide}
3619     */
3620    protected ViewGroup.LayoutParams mLayoutParams;
3621
3622    /**
3623     * The view flags hold various views states.
3624     * {@hide}
3625     */
3626    @ViewDebug.ExportedProperty(formatToHexString = true)
3627    int mViewFlags;
3628
3629    static class TransformationInfo {
3630        /**
3631         * The transform matrix for the View. This transform is calculated internally
3632         * based on the translation, rotation, and scale properties.
3633         *
3634         * Do *not* use this variable directly; instead call getMatrix(), which will
3635         * load the value from the View's RenderNode.
3636         */
3637        private final Matrix mMatrix = new Matrix();
3638
3639        /**
3640         * The inverse transform matrix for the View. This transform is calculated
3641         * internally based on the translation, rotation, and scale properties.
3642         *
3643         * Do *not* use this variable directly; instead call getInverseMatrix(),
3644         * which will load the value from the View's RenderNode.
3645         */
3646        private Matrix mInverseMatrix;
3647
3648        /**
3649         * The opacity of the View. This is a value from 0 to 1, where 0 means
3650         * completely transparent and 1 means completely opaque.
3651         */
3652        @ViewDebug.ExportedProperty
3653        float mAlpha = 1f;
3654
3655        /**
3656         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3657         * property only used by transitions, which is composited with the other alpha
3658         * values to calculate the final visual alpha value.
3659         */
3660        float mTransitionAlpha = 1f;
3661    }
3662
3663    /** @hide */
3664    public TransformationInfo mTransformationInfo;
3665
3666    /**
3667     * Current clip bounds. to which all drawing of this view are constrained.
3668     */
3669    Rect mClipBounds = null;
3670
3671    private boolean mLastIsOpaque;
3672
3673    /**
3674     * The distance in pixels from the left edge of this view's parent
3675     * to the left edge of this view.
3676     * {@hide}
3677     */
3678    @ViewDebug.ExportedProperty(category = "layout")
3679    protected int mLeft;
3680    /**
3681     * The distance in pixels from the left edge of this view's parent
3682     * to the right edge of this view.
3683     * {@hide}
3684     */
3685    @ViewDebug.ExportedProperty(category = "layout")
3686    protected int mRight;
3687    /**
3688     * The distance in pixels from the top edge of this view's parent
3689     * to the top edge of this view.
3690     * {@hide}
3691     */
3692    @ViewDebug.ExportedProperty(category = "layout")
3693    protected int mTop;
3694    /**
3695     * The distance in pixels from the top edge of this view's parent
3696     * to the bottom edge of this view.
3697     * {@hide}
3698     */
3699    @ViewDebug.ExportedProperty(category = "layout")
3700    protected int mBottom;
3701
3702    /**
3703     * The offset, in pixels, by which the content of this view is scrolled
3704     * horizontally.
3705     * {@hide}
3706     */
3707    @ViewDebug.ExportedProperty(category = "scrolling")
3708    protected int mScrollX;
3709    /**
3710     * The offset, in pixels, by which the content of this view is scrolled
3711     * vertically.
3712     * {@hide}
3713     */
3714    @ViewDebug.ExportedProperty(category = "scrolling")
3715    protected int mScrollY;
3716
3717    /**
3718     * The left padding in pixels, that is the distance in pixels between the
3719     * left edge of this view and the left edge of its content.
3720     * {@hide}
3721     */
3722    @ViewDebug.ExportedProperty(category = "padding")
3723    protected int mPaddingLeft = 0;
3724    /**
3725     * The right padding in pixels, that is the distance in pixels between the
3726     * right edge of this view and the right edge of its content.
3727     * {@hide}
3728     */
3729    @ViewDebug.ExportedProperty(category = "padding")
3730    protected int mPaddingRight = 0;
3731    /**
3732     * The top padding in pixels, that is the distance in pixels between the
3733     * top edge of this view and the top edge of its content.
3734     * {@hide}
3735     */
3736    @ViewDebug.ExportedProperty(category = "padding")
3737    protected int mPaddingTop;
3738    /**
3739     * The bottom padding in pixels, that is the distance in pixels between the
3740     * bottom edge of this view and the bottom edge of its content.
3741     * {@hide}
3742     */
3743    @ViewDebug.ExportedProperty(category = "padding")
3744    protected int mPaddingBottom;
3745
3746    /**
3747     * The layout insets in pixels, that is the distance in pixels between the
3748     * visible edges of this view its bounds.
3749     */
3750    private Insets mLayoutInsets;
3751
3752    /**
3753     * Briefly describes the view and is primarily used for accessibility support.
3754     */
3755    private CharSequence mContentDescription;
3756
3757    /**
3758     * Specifies the id of a view for which this view serves as a label for
3759     * accessibility purposes.
3760     */
3761    private int mLabelForId = View.NO_ID;
3762
3763    /**
3764     * Predicate for matching labeled view id with its label for
3765     * accessibility purposes.
3766     */
3767    private MatchLabelForPredicate mMatchLabelForPredicate;
3768
3769    /**
3770     * Specifies a view before which this one is visited in accessibility traversal.
3771     */
3772    private int mAccessibilityTraversalBeforeId = NO_ID;
3773
3774    /**
3775     * Specifies a view after which this one is visited in accessibility traversal.
3776     */
3777    private int mAccessibilityTraversalAfterId = NO_ID;
3778
3779    /**
3780     * Predicate for matching a view by its id.
3781     */
3782    private MatchIdPredicate mMatchIdPredicate;
3783
3784    /**
3785     * Cache the paddingRight set by the user to append to the scrollbar's size.
3786     *
3787     * @hide
3788     */
3789    @ViewDebug.ExportedProperty(category = "padding")
3790    protected int mUserPaddingRight;
3791
3792    /**
3793     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3794     *
3795     * @hide
3796     */
3797    @ViewDebug.ExportedProperty(category = "padding")
3798    protected int mUserPaddingBottom;
3799
3800    /**
3801     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3802     *
3803     * @hide
3804     */
3805    @ViewDebug.ExportedProperty(category = "padding")
3806    protected int mUserPaddingLeft;
3807
3808    /**
3809     * Cache the paddingStart set by the user to append to the scrollbar's size.
3810     *
3811     */
3812    @ViewDebug.ExportedProperty(category = "padding")
3813    int mUserPaddingStart;
3814
3815    /**
3816     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3817     *
3818     */
3819    @ViewDebug.ExportedProperty(category = "padding")
3820    int mUserPaddingEnd;
3821
3822    /**
3823     * Cache initial left padding.
3824     *
3825     * @hide
3826     */
3827    int mUserPaddingLeftInitial;
3828
3829    /**
3830     * Cache initial right padding.
3831     *
3832     * @hide
3833     */
3834    int mUserPaddingRightInitial;
3835
3836    /**
3837     * Default undefined padding
3838     */
3839    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3840
3841    /**
3842     * Cache if a left padding has been defined
3843     */
3844    private boolean mLeftPaddingDefined = false;
3845
3846    /**
3847     * Cache if a right padding has been defined
3848     */
3849    private boolean mRightPaddingDefined = false;
3850
3851    /**
3852     * @hide
3853     */
3854    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3855    /**
3856     * @hide
3857     */
3858    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3859
3860    private LongSparseLongArray mMeasureCache;
3861
3862    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3863    private Drawable mBackground;
3864    private TintInfo mBackgroundTint;
3865
3866    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3867    private ForegroundInfo mForegroundInfo;
3868
3869    private Drawable mScrollIndicatorDrawable;
3870
3871    /**
3872     * RenderNode used for backgrounds.
3873     * <p>
3874     * When non-null and valid, this is expected to contain an up-to-date copy
3875     * of the background drawable. It is cleared on temporary detach, and reset
3876     * on cleanup.
3877     */
3878    private RenderNode mBackgroundRenderNode;
3879
3880    private int mBackgroundResource;
3881    private boolean mBackgroundSizeChanged;
3882
3883    /** The default focus highlight.
3884     * @see #mDefaultFocusHighlightEnabled
3885     * @see Drawable#hasFocusStateSpecified()
3886     */
3887    private Drawable mDefaultFocusHighlight;
3888    private Drawable mDefaultFocusHighlightCache;
3889    private boolean mDefaultFocusHighlightSizeChanged;
3890    /**
3891     * True if the default focus highlight is needed on the target device.
3892     */
3893    private static boolean sUseDefaultFocusHighlight;
3894
3895    private String mTransitionName;
3896
3897    static class TintInfo {
3898        ColorStateList mTintList;
3899        PorterDuff.Mode mTintMode;
3900        boolean mHasTintMode;
3901        boolean mHasTintList;
3902    }
3903
3904    private static class ForegroundInfo {
3905        private Drawable mDrawable;
3906        private TintInfo mTintInfo;
3907        private int mGravity = Gravity.FILL;
3908        private boolean mInsidePadding = true;
3909        private boolean mBoundsChanged = true;
3910        private final Rect mSelfBounds = new Rect();
3911        private final Rect mOverlayBounds = new Rect();
3912    }
3913
3914    static class ListenerInfo {
3915        /**
3916         * Listener used to dispatch focus change events.
3917         * This field should be made private, so it is hidden from the SDK.
3918         * {@hide}
3919         */
3920        protected OnFocusChangeListener mOnFocusChangeListener;
3921
3922        /**
3923         * Listeners for layout change events.
3924         */
3925        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3926
3927        protected OnScrollChangeListener mOnScrollChangeListener;
3928
3929        /**
3930         * Listeners for attach events.
3931         */
3932        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3933
3934        /**
3935         * Listener used to dispatch click events.
3936         * This field should be made private, so it is hidden from the SDK.
3937         * {@hide}
3938         */
3939        public OnClickListener mOnClickListener;
3940
3941        /**
3942         * Listener used to dispatch long click events.
3943         * This field should be made private, so it is hidden from the SDK.
3944         * {@hide}
3945         */
3946        protected OnLongClickListener mOnLongClickListener;
3947
3948        /**
3949         * Listener used to dispatch context click events. This field should be made private, so it
3950         * is hidden from the SDK.
3951         * {@hide}
3952         */
3953        protected OnContextClickListener mOnContextClickListener;
3954
3955        /**
3956         * Listener used to build the context menu.
3957         * This field should be made private, so it is hidden from the SDK.
3958         * {@hide}
3959         */
3960        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3961
3962        private OnKeyListener mOnKeyListener;
3963
3964        private OnTouchListener mOnTouchListener;
3965
3966        private OnHoverListener mOnHoverListener;
3967
3968        private OnGenericMotionListener mOnGenericMotionListener;
3969
3970        private OnDragListener mOnDragListener;
3971
3972        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3973
3974        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3975
3976        OnCapturedPointerListener mOnCapturedPointerListener;
3977    }
3978
3979    ListenerInfo mListenerInfo;
3980
3981    private static class TooltipInfo {
3982        /**
3983         * Text to be displayed in a tooltip popup.
3984         */
3985        @Nullable
3986        CharSequence mTooltipText;
3987
3988        /**
3989         * View-relative position of the tooltip anchor point.
3990         */
3991        int mAnchorX;
3992        int mAnchorY;
3993
3994        /**
3995         * The tooltip popup.
3996         */
3997        @Nullable
3998        TooltipPopup mTooltipPopup;
3999
4000        /**
4001         * Set to true if the tooltip was shown as a result of a long click.
4002         */
4003        boolean mTooltipFromLongClick;
4004
4005        /**
4006         * Keep these Runnables so that they can be used to reschedule.
4007         */
4008        Runnable mShowTooltipRunnable;
4009        Runnable mHideTooltipRunnable;
4010    }
4011
4012    TooltipInfo mTooltipInfo;
4013
4014    // Temporary values used to hold (x,y) coordinates when delegating from the
4015    // two-arg performLongClick() method to the legacy no-arg version.
4016    private float mLongClickX = Float.NaN;
4017    private float mLongClickY = Float.NaN;
4018
4019    /**
4020     * The application environment this view lives in.
4021     * This field should be made private, so it is hidden from the SDK.
4022     * {@hide}
4023     */
4024    @ViewDebug.ExportedProperty(deepExport = true)
4025    protected Context mContext;
4026
4027    private final Resources mResources;
4028
4029    private ScrollabilityCache mScrollCache;
4030
4031    private int[] mDrawableState = null;
4032
4033    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4034
4035    /**
4036     * Animator that automatically runs based on state changes.
4037     */
4038    private StateListAnimator mStateListAnimator;
4039
4040    /**
4041     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4042     * the user may specify which view to go to next.
4043     */
4044    private int mNextFocusLeftId = View.NO_ID;
4045
4046    /**
4047     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4048     * the user may specify which view to go to next.
4049     */
4050    private int mNextFocusRightId = View.NO_ID;
4051
4052    /**
4053     * When this view has focus and the next focus is {@link #FOCUS_UP},
4054     * the user may specify which view to go to next.
4055     */
4056    private int mNextFocusUpId = View.NO_ID;
4057
4058    /**
4059     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4060     * the user may specify which view to go to next.
4061     */
4062    private int mNextFocusDownId = View.NO_ID;
4063
4064    /**
4065     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4066     * the user may specify which view to go to next.
4067     */
4068    int mNextFocusForwardId = View.NO_ID;
4069
4070    /**
4071     * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4072     *
4073     * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4074     */
4075    int mNextClusterForwardId = View.NO_ID;
4076
4077    /**
4078     * Whether this View should use a default focus highlight when it gets focused but doesn't
4079     * have {@link android.R.attr#state_focused} defined in its background.
4080     */
4081    boolean mDefaultFocusHighlightEnabled = true;
4082
4083    private CheckForLongPress mPendingCheckForLongPress;
4084    private CheckForTap mPendingCheckForTap = null;
4085    private PerformClick mPerformClick;
4086    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4087
4088    private UnsetPressedState mUnsetPressedState;
4089
4090    /**
4091     * Whether the long press's action has been invoked.  The tap's action is invoked on the
4092     * up event while a long press is invoked as soon as the long press duration is reached, so
4093     * a long press could be performed before the tap is checked, in which case the tap's action
4094     * should not be invoked.
4095     */
4096    private boolean mHasPerformedLongPress;
4097
4098    /**
4099     * Whether a context click button is currently pressed down. This is true when the stylus is
4100     * touching the screen and the primary button has been pressed, or if a mouse's right button is
4101     * pressed. This is false once the button is released or if the stylus has been lifted.
4102     */
4103    private boolean mInContextButtonPress;
4104
4105    /**
4106     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4107     * true after a stylus button press has occured, when the next up event should not be recognized
4108     * as a tap.
4109     */
4110    private boolean mIgnoreNextUpEvent;
4111
4112    /**
4113     * The minimum height of the view. We'll try our best to have the height
4114     * of this view to at least this amount.
4115     */
4116    @ViewDebug.ExportedProperty(category = "measurement")
4117    private int mMinHeight;
4118
4119    /**
4120     * The minimum width of the view. We'll try our best to have the width
4121     * of this view to at least this amount.
4122     */
4123    @ViewDebug.ExportedProperty(category = "measurement")
4124    private int mMinWidth;
4125
4126    /**
4127     * The delegate to handle touch events that are physically in this view
4128     * but should be handled by another view.
4129     */
4130    private TouchDelegate mTouchDelegate = null;
4131
4132    /**
4133     * Solid color to use as a background when creating the drawing cache. Enables
4134     * the cache to use 16 bit bitmaps instead of 32 bit.
4135     */
4136    private int mDrawingCacheBackgroundColor = 0;
4137
4138    /**
4139     * Special tree observer used when mAttachInfo is null.
4140     */
4141    private ViewTreeObserver mFloatingTreeObserver;
4142
4143    /**
4144     * Cache the touch slop from the context that created the view.
4145     */
4146    private int mTouchSlop;
4147
4148    /**
4149     * Object that handles automatic animation of view properties.
4150     */
4151    private ViewPropertyAnimator mAnimator = null;
4152
4153    /**
4154     * List of registered FrameMetricsObservers.
4155     */
4156    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4157
4158    /**
4159     * Flag indicating that a drag can cross window boundaries.  When
4160     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4161     * with this flag set, all visible applications with targetSdkVersion >=
4162     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4163     * in the drag operation and receive the dragged content.
4164     *
4165     * <p>If this is the only flag set, then the drag recipient will only have access to text data
4166     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4167     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4168     */
4169    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4170
4171    /**
4172     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4173     * request read access to the content URI(s) contained in the {@link ClipData} object.
4174     * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4175     */
4176    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4177
4178    /**
4179     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4180     * request write access to the content URI(s) contained in the {@link ClipData} object.
4181     * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4182     */
4183    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4184
4185    /**
4186     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4187     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4188     * reboots until explicitly revoked with
4189     * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4190     * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4191     */
4192    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4193            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4194
4195    /**
4196     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4197     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4198     * match against the original granted URI.
4199     * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4200     */
4201    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4202            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4203
4204    /**
4205     * Flag indicating that the drag shadow will be opaque.  When
4206     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4207     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4208     */
4209    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4210
4211    /**
4212     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4213     */
4214    private float mVerticalScrollFactor;
4215
4216    /**
4217     * Position of the vertical scroll bar.
4218     */
4219    private int mVerticalScrollbarPosition;
4220
4221    /**
4222     * Position the scroll bar at the default position as determined by the system.
4223     */
4224    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4225
4226    /**
4227     * Position the scroll bar along the left edge.
4228     */
4229    public static final int SCROLLBAR_POSITION_LEFT = 1;
4230
4231    /**
4232     * Position the scroll bar along the right edge.
4233     */
4234    public static final int SCROLLBAR_POSITION_RIGHT = 2;
4235
4236    /**
4237     * Indicates that the view does not have a layer.
4238     *
4239     * @see #getLayerType()
4240     * @see #setLayerType(int, android.graphics.Paint)
4241     * @see #LAYER_TYPE_SOFTWARE
4242     * @see #LAYER_TYPE_HARDWARE
4243     */
4244    public static final int LAYER_TYPE_NONE = 0;
4245
4246    /**
4247     * <p>Indicates that the view has a software layer. A software layer is backed
4248     * by a bitmap and causes the view to be rendered using Android's software
4249     * rendering pipeline, even if hardware acceleration is enabled.</p>
4250     *
4251     * <p>Software layers have various usages:</p>
4252     * <p>When the application is not using hardware acceleration, a software layer
4253     * is useful to apply a specific color filter and/or blending mode and/or
4254     * translucency to a view and all its children.</p>
4255     * <p>When the application is using hardware acceleration, a software layer
4256     * is useful to render drawing primitives not supported by the hardware
4257     * accelerated pipeline. It can also be used to cache a complex view tree
4258     * into a texture and reduce the complexity of drawing operations. For instance,
4259     * when animating a complex view tree with a translation, a software layer can
4260     * be used to render the view tree only once.</p>
4261     * <p>Software layers should be avoided when the affected view tree updates
4262     * often. Every update will require to re-render the software layer, which can
4263     * potentially be slow (particularly when hardware acceleration is turned on
4264     * since the layer will have to be uploaded into a hardware texture after every
4265     * update.)</p>
4266     *
4267     * @see #getLayerType()
4268     * @see #setLayerType(int, android.graphics.Paint)
4269     * @see #LAYER_TYPE_NONE
4270     * @see #LAYER_TYPE_HARDWARE
4271     */
4272    public static final int LAYER_TYPE_SOFTWARE = 1;
4273
4274    /**
4275     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4276     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4277     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4278     * rendering pipeline, but only if hardware acceleration is turned on for the
4279     * view hierarchy. When hardware acceleration is turned off, hardware layers
4280     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4281     *
4282     * <p>A hardware layer is useful to apply a specific color filter and/or
4283     * blending mode and/or translucency to a view and all its children.</p>
4284     * <p>A hardware layer can be used to cache a complex view tree into a
4285     * texture and reduce the complexity of drawing operations. For instance,
4286     * when animating a complex view tree with a translation, a hardware layer can
4287     * be used to render the view tree only once.</p>
4288     * <p>A hardware layer can also be used to increase the rendering quality when
4289     * rotation transformations are applied on a view. It can also be used to
4290     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4291     *
4292     * @see #getLayerType()
4293     * @see #setLayerType(int, android.graphics.Paint)
4294     * @see #LAYER_TYPE_NONE
4295     * @see #LAYER_TYPE_SOFTWARE
4296     */
4297    public static final int LAYER_TYPE_HARDWARE = 2;
4298
4299    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4300            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4301            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4302            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4303    })
4304    int mLayerType = LAYER_TYPE_NONE;
4305    Paint mLayerPaint;
4306
4307    /**
4308     * Set to true when drawing cache is enabled and cannot be created.
4309     *
4310     * @hide
4311     */
4312    public boolean mCachingFailed;
4313    private Bitmap mDrawingCache;
4314    private Bitmap mUnscaledDrawingCache;
4315
4316    /**
4317     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4318     * <p>
4319     * When non-null and valid, this is expected to contain an up-to-date copy
4320     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4321     * cleanup.
4322     */
4323    final RenderNode mRenderNode;
4324
4325    /**
4326     * Set to true when the view is sending hover accessibility events because it
4327     * is the innermost hovered view.
4328     */
4329    private boolean mSendingHoverAccessibilityEvents;
4330
4331    /**
4332     * Delegate for injecting accessibility functionality.
4333     */
4334    AccessibilityDelegate mAccessibilityDelegate;
4335
4336    /**
4337     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4338     * and add/remove objects to/from the overlay directly through the Overlay methods.
4339     */
4340    ViewOverlay mOverlay;
4341
4342    /**
4343     * The currently active parent view for receiving delegated nested scrolling events.
4344     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4345     * by {@link #stopNestedScroll()} at the same point where we clear
4346     * requestDisallowInterceptTouchEvent.
4347     */
4348    private ViewParent mNestedScrollingParent;
4349
4350    /**
4351     * Consistency verifier for debugging purposes.
4352     * @hide
4353     */
4354    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4355            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4356                    new InputEventConsistencyVerifier(this, 0) : null;
4357
4358    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4359
4360    private int[] mTempNestedScrollConsumed;
4361
4362    /**
4363     * An overlay is going to draw this View instead of being drawn as part of this
4364     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4365     * when this view is invalidated.
4366     */
4367    GhostView mGhostView;
4368
4369    /**
4370     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4371     * @hide
4372     */
4373    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4374    public String[] mAttributes;
4375
4376    /**
4377     * Maps a Resource id to its name.
4378     */
4379    private static SparseArray<String> mAttributeMap;
4380
4381    /**
4382     * Queue of pending runnables. Used to postpone calls to post() until this
4383     * view is attached and has a handler.
4384     */
4385    private HandlerActionQueue mRunQueue;
4386
4387    /**
4388     * The pointer icon when the mouse hovers on this view. The default is null.
4389     */
4390    private PointerIcon mPointerIcon;
4391
4392    /**
4393     * @hide
4394     */
4395    String mStartActivityRequestWho;
4396
4397    @Nullable
4398    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4399
4400    /** Used to delay visibility updates sent to the autofill manager */
4401    private Handler mVisibilityChangeForAutofillHandler;
4402
4403    /**
4404     * Simple constructor to use when creating a view from code.
4405     *
4406     * @param context The Context the view is running in, through which it can
4407     *        access the current theme, resources, etc.
4408     */
4409    public View(Context context) {
4410        mContext = context;
4411        mResources = context != null ? context.getResources() : null;
4412        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4413        // Set some flags defaults
4414        mPrivateFlags2 =
4415                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4416                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4417                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4418                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4419                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4420                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4421        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4422        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4423        mUserPaddingStart = UNDEFINED_PADDING;
4424        mUserPaddingEnd = UNDEFINED_PADDING;
4425        mRenderNode = RenderNode.create(getClass().getName(), this);
4426
4427        if (!sCompatibilityDone && context != null) {
4428            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4429
4430            // Older apps may need this compatibility hack for measurement.
4431            sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4432
4433            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4434            // of whether a layout was requested on that View.
4435            sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4436
4437            Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4438
4439            // In M and newer, our widgets can pass a "hint" value in the size
4440            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4441            // know what the expected parent size is going to be, so e.g. list items can size
4442            // themselves at 1/3 the size of their container. It breaks older apps though,
4443            // specifically apps that use some popular open source libraries.
4444            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4445
4446            // Old versions of the platform would give different results from
4447            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4448            // modes, so we always need to run an additional EXACTLY pass.
4449            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4450
4451            // Prior to N, layout params could change without requiring a
4452            // subsequent call to setLayoutParams() and they would usually
4453            // work. Partial layout breaks this assumption.
4454            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4455
4456            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4457            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4458            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4459
4460            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4461            // in apps so we target check it to avoid breaking existing apps.
4462            sPreserveMarginParamsInLayoutParamConversion =
4463                    targetSdkVersion >= Build.VERSION_CODES.N;
4464
4465            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4466
4467            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4468
4469            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4470
4471            sUseDefaultFocusHighlight = context.getResources().getBoolean(
4472                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
4473
4474            sCompatibilityDone = true;
4475        }
4476    }
4477
4478    /**
4479     * Constructor that is called when inflating a view from XML. This is called
4480     * when a view is being constructed from an XML file, supplying attributes
4481     * that were specified in the XML file. This version uses a default style of
4482     * 0, so the only attribute values applied are those in the Context's Theme
4483     * and the given AttributeSet.
4484     *
4485     * <p>
4486     * The method onFinishInflate() will be called after all children have been
4487     * added.
4488     *
4489     * @param context The Context the view is running in, through which it can
4490     *        access the current theme, resources, etc.
4491     * @param attrs The attributes of the XML tag that is inflating the view.
4492     * @see #View(Context, AttributeSet, int)
4493     */
4494    public View(Context context, @Nullable AttributeSet attrs) {
4495        this(context, attrs, 0);
4496    }
4497
4498    /**
4499     * Perform inflation from XML and apply a class-specific base style from a
4500     * theme attribute. This constructor of View allows subclasses to use their
4501     * own base style when they are inflating. For example, a Button class's
4502     * constructor would call this version of the super class constructor and
4503     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4504     * allows the theme's button style to modify all of the base view attributes
4505     * (in particular its background) as well as the Button class's attributes.
4506     *
4507     * @param context The Context the view is running in, through which it can
4508     *        access the current theme, resources, etc.
4509     * @param attrs The attributes of the XML tag that is inflating the view.
4510     * @param defStyleAttr An attribute in the current theme that contains a
4511     *        reference to a style resource that supplies default values for
4512     *        the view. Can be 0 to not look for defaults.
4513     * @see #View(Context, AttributeSet)
4514     */
4515    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4516        this(context, attrs, defStyleAttr, 0);
4517    }
4518
4519    /**
4520     * Perform inflation from XML and apply a class-specific base style from a
4521     * theme attribute or style resource. This constructor of View allows
4522     * subclasses to use their own base style when they are inflating.
4523     * <p>
4524     * When determining the final value of a particular attribute, there are
4525     * four inputs that come into play:
4526     * <ol>
4527     * <li>Any attribute values in the given AttributeSet.
4528     * <li>The style resource specified in the AttributeSet (named "style").
4529     * <li>The default style specified by <var>defStyleAttr</var>.
4530     * <li>The default style specified by <var>defStyleRes</var>.
4531     * <li>The base values in this theme.
4532     * </ol>
4533     * <p>
4534     * Each of these inputs is considered in-order, with the first listed taking
4535     * precedence over the following ones. In other words, if in the
4536     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4537     * , then the button's text will <em>always</em> be black, regardless of
4538     * what is specified in any of the styles.
4539     *
4540     * @param context The Context the view is running in, through which it can
4541     *        access the current theme, resources, etc.
4542     * @param attrs The attributes of the XML tag that is inflating the view.
4543     * @param defStyleAttr An attribute in the current theme that contains a
4544     *        reference to a style resource that supplies default values for
4545     *        the view. Can be 0 to not look for defaults.
4546     * @param defStyleRes A resource identifier of a style resource that
4547     *        supplies default values for the view, used only if
4548     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4549     *        to not look for defaults.
4550     * @see #View(Context, AttributeSet, int)
4551     */
4552    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4553        this(context);
4554
4555        final TypedArray a = context.obtainStyledAttributes(
4556                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4557
4558        if (mDebugViewAttributes) {
4559            saveAttributeData(attrs, a);
4560        }
4561
4562        Drawable background = null;
4563
4564        int leftPadding = -1;
4565        int topPadding = -1;
4566        int rightPadding = -1;
4567        int bottomPadding = -1;
4568        int startPadding = UNDEFINED_PADDING;
4569        int endPadding = UNDEFINED_PADDING;
4570
4571        int padding = -1;
4572        int paddingHorizontal = -1;
4573        int paddingVertical = -1;
4574
4575        int viewFlagValues = 0;
4576        int viewFlagMasks = 0;
4577
4578        boolean setScrollContainer = false;
4579
4580        int x = 0;
4581        int y = 0;
4582
4583        float tx = 0;
4584        float ty = 0;
4585        float tz = 0;
4586        float elevation = 0;
4587        float rotation = 0;
4588        float rotationX = 0;
4589        float rotationY = 0;
4590        float sx = 1f;
4591        float sy = 1f;
4592        boolean transformSet = false;
4593
4594        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4595        int overScrollMode = mOverScrollMode;
4596        boolean initializeScrollbars = false;
4597        boolean initializeScrollIndicators = false;
4598
4599        boolean startPaddingDefined = false;
4600        boolean endPaddingDefined = false;
4601        boolean leftPaddingDefined = false;
4602        boolean rightPaddingDefined = false;
4603
4604        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4605
4606        // Set default values.
4607        viewFlagValues |= FOCUSABLE_AUTO;
4608        viewFlagMasks |= FOCUSABLE_AUTO;
4609
4610        final int N = a.getIndexCount();
4611        for (int i = 0; i < N; i++) {
4612            int attr = a.getIndex(i);
4613            switch (attr) {
4614                case com.android.internal.R.styleable.View_background:
4615                    background = a.getDrawable(attr);
4616                    break;
4617                case com.android.internal.R.styleable.View_padding:
4618                    padding = a.getDimensionPixelSize(attr, -1);
4619                    mUserPaddingLeftInitial = padding;
4620                    mUserPaddingRightInitial = padding;
4621                    leftPaddingDefined = true;
4622                    rightPaddingDefined = true;
4623                    break;
4624                case com.android.internal.R.styleable.View_paddingHorizontal:
4625                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4626                    mUserPaddingLeftInitial = paddingHorizontal;
4627                    mUserPaddingRightInitial = paddingHorizontal;
4628                    leftPaddingDefined = true;
4629                    rightPaddingDefined = true;
4630                    break;
4631                case com.android.internal.R.styleable.View_paddingVertical:
4632                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4633                    break;
4634                 case com.android.internal.R.styleable.View_paddingLeft:
4635                    leftPadding = a.getDimensionPixelSize(attr, -1);
4636                    mUserPaddingLeftInitial = leftPadding;
4637                    leftPaddingDefined = true;
4638                    break;
4639                case com.android.internal.R.styleable.View_paddingTop:
4640                    topPadding = a.getDimensionPixelSize(attr, -1);
4641                    break;
4642                case com.android.internal.R.styleable.View_paddingRight:
4643                    rightPadding = a.getDimensionPixelSize(attr, -1);
4644                    mUserPaddingRightInitial = rightPadding;
4645                    rightPaddingDefined = true;
4646                    break;
4647                case com.android.internal.R.styleable.View_paddingBottom:
4648                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4649                    break;
4650                case com.android.internal.R.styleable.View_paddingStart:
4651                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4652                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4653                    break;
4654                case com.android.internal.R.styleable.View_paddingEnd:
4655                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4656                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4657                    break;
4658                case com.android.internal.R.styleable.View_scrollX:
4659                    x = a.getDimensionPixelOffset(attr, 0);
4660                    break;
4661                case com.android.internal.R.styleable.View_scrollY:
4662                    y = a.getDimensionPixelOffset(attr, 0);
4663                    break;
4664                case com.android.internal.R.styleable.View_alpha:
4665                    setAlpha(a.getFloat(attr, 1f));
4666                    break;
4667                case com.android.internal.R.styleable.View_transformPivotX:
4668                    setPivotX(a.getDimension(attr, 0));
4669                    break;
4670                case com.android.internal.R.styleable.View_transformPivotY:
4671                    setPivotY(a.getDimension(attr, 0));
4672                    break;
4673                case com.android.internal.R.styleable.View_translationX:
4674                    tx = a.getDimension(attr, 0);
4675                    transformSet = true;
4676                    break;
4677                case com.android.internal.R.styleable.View_translationY:
4678                    ty = a.getDimension(attr, 0);
4679                    transformSet = true;
4680                    break;
4681                case com.android.internal.R.styleable.View_translationZ:
4682                    tz = a.getDimension(attr, 0);
4683                    transformSet = true;
4684                    break;
4685                case com.android.internal.R.styleable.View_elevation:
4686                    elevation = a.getDimension(attr, 0);
4687                    transformSet = true;
4688                    break;
4689                case com.android.internal.R.styleable.View_rotation:
4690                    rotation = a.getFloat(attr, 0);
4691                    transformSet = true;
4692                    break;
4693                case com.android.internal.R.styleable.View_rotationX:
4694                    rotationX = a.getFloat(attr, 0);
4695                    transformSet = true;
4696                    break;
4697                case com.android.internal.R.styleable.View_rotationY:
4698                    rotationY = a.getFloat(attr, 0);
4699                    transformSet = true;
4700                    break;
4701                case com.android.internal.R.styleable.View_scaleX:
4702                    sx = a.getFloat(attr, 1f);
4703                    transformSet = true;
4704                    break;
4705                case com.android.internal.R.styleable.View_scaleY:
4706                    sy = a.getFloat(attr, 1f);
4707                    transformSet = true;
4708                    break;
4709                case com.android.internal.R.styleable.View_id:
4710                    mID = a.getResourceId(attr, NO_ID);
4711                    break;
4712                case com.android.internal.R.styleable.View_tag:
4713                    mTag = a.getText(attr);
4714                    break;
4715                case com.android.internal.R.styleable.View_fitsSystemWindows:
4716                    if (a.getBoolean(attr, false)) {
4717                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4718                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4719                    }
4720                    break;
4721                case com.android.internal.R.styleable.View_focusable:
4722                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4723                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4724                        viewFlagMasks |= FOCUSABLE_MASK;
4725                    }
4726                    break;
4727                case com.android.internal.R.styleable.View_focusableInTouchMode:
4728                    if (a.getBoolean(attr, false)) {
4729                        // unset auto focus since focusableInTouchMode implies explicit focusable
4730                        viewFlagValues &= ~FOCUSABLE_AUTO;
4731                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4732                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4733                    }
4734                    break;
4735                case com.android.internal.R.styleable.View_clickable:
4736                    if (a.getBoolean(attr, false)) {
4737                        viewFlagValues |= CLICKABLE;
4738                        viewFlagMasks |= CLICKABLE;
4739                    }
4740                    break;
4741                case com.android.internal.R.styleable.View_longClickable:
4742                    if (a.getBoolean(attr, false)) {
4743                        viewFlagValues |= LONG_CLICKABLE;
4744                        viewFlagMasks |= LONG_CLICKABLE;
4745                    }
4746                    break;
4747                case com.android.internal.R.styleable.View_contextClickable:
4748                    if (a.getBoolean(attr, false)) {
4749                        viewFlagValues |= CONTEXT_CLICKABLE;
4750                        viewFlagMasks |= CONTEXT_CLICKABLE;
4751                    }
4752                    break;
4753                case com.android.internal.R.styleable.View_saveEnabled:
4754                    if (!a.getBoolean(attr, true)) {
4755                        viewFlagValues |= SAVE_DISABLED;
4756                        viewFlagMasks |= SAVE_DISABLED_MASK;
4757                    }
4758                    break;
4759                case com.android.internal.R.styleable.View_duplicateParentState:
4760                    if (a.getBoolean(attr, false)) {
4761                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4762                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4763                    }
4764                    break;
4765                case com.android.internal.R.styleable.View_visibility:
4766                    final int visibility = a.getInt(attr, 0);
4767                    if (visibility != 0) {
4768                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4769                        viewFlagMasks |= VISIBILITY_MASK;
4770                    }
4771                    break;
4772                case com.android.internal.R.styleable.View_layoutDirection:
4773                    // Clear any layout direction flags (included resolved bits) already set
4774                    mPrivateFlags2 &=
4775                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4776                    // Set the layout direction flags depending on the value of the attribute
4777                    final int layoutDirection = a.getInt(attr, -1);
4778                    final int value = (layoutDirection != -1) ?
4779                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4780                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4781                    break;
4782                case com.android.internal.R.styleable.View_drawingCacheQuality:
4783                    final int cacheQuality = a.getInt(attr, 0);
4784                    if (cacheQuality != 0) {
4785                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4786                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4787                    }
4788                    break;
4789                case com.android.internal.R.styleable.View_contentDescription:
4790                    setContentDescription(a.getString(attr));
4791                    break;
4792                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4793                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4794                    break;
4795                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4796                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4797                    break;
4798                case com.android.internal.R.styleable.View_labelFor:
4799                    setLabelFor(a.getResourceId(attr, NO_ID));
4800                    break;
4801                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4802                    if (!a.getBoolean(attr, true)) {
4803                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4804                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4805                    }
4806                    break;
4807                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4808                    if (!a.getBoolean(attr, true)) {
4809                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4810                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4811                    }
4812                    break;
4813                case R.styleable.View_scrollbars:
4814                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4815                    if (scrollbars != SCROLLBARS_NONE) {
4816                        viewFlagValues |= scrollbars;
4817                        viewFlagMasks |= SCROLLBARS_MASK;
4818                        initializeScrollbars = true;
4819                    }
4820                    break;
4821                //noinspection deprecation
4822                case R.styleable.View_fadingEdge:
4823                    if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4824                        // Ignore the attribute starting with ICS
4825                        break;
4826                    }
4827                    // With builds < ICS, fall through and apply fading edges
4828                case R.styleable.View_requiresFadingEdge:
4829                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4830                    if (fadingEdge != FADING_EDGE_NONE) {
4831                        viewFlagValues |= fadingEdge;
4832                        viewFlagMasks |= FADING_EDGE_MASK;
4833                        initializeFadingEdgeInternal(a);
4834                    }
4835                    break;
4836                case R.styleable.View_scrollbarStyle:
4837                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4838                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4839                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4840                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4841                    }
4842                    break;
4843                case R.styleable.View_isScrollContainer:
4844                    setScrollContainer = true;
4845                    if (a.getBoolean(attr, false)) {
4846                        setScrollContainer(true);
4847                    }
4848                    break;
4849                case com.android.internal.R.styleable.View_keepScreenOn:
4850                    if (a.getBoolean(attr, false)) {
4851                        viewFlagValues |= KEEP_SCREEN_ON;
4852                        viewFlagMasks |= KEEP_SCREEN_ON;
4853                    }
4854                    break;
4855                case R.styleable.View_filterTouchesWhenObscured:
4856                    if (a.getBoolean(attr, false)) {
4857                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4858                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4859                    }
4860                    break;
4861                case R.styleable.View_nextFocusLeft:
4862                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4863                    break;
4864                case R.styleable.View_nextFocusRight:
4865                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4866                    break;
4867                case R.styleable.View_nextFocusUp:
4868                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4869                    break;
4870                case R.styleable.View_nextFocusDown:
4871                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4872                    break;
4873                case R.styleable.View_nextFocusForward:
4874                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4875                    break;
4876                case R.styleable.View_nextClusterForward:
4877                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4878                    break;
4879                case R.styleable.View_minWidth:
4880                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4881                    break;
4882                case R.styleable.View_minHeight:
4883                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4884                    break;
4885                case R.styleable.View_onClick:
4886                    if (context.isRestricted()) {
4887                        throw new IllegalStateException("The android:onClick attribute cannot "
4888                                + "be used within a restricted context");
4889                    }
4890
4891                    final String handlerName = a.getString(attr);
4892                    if (handlerName != null) {
4893                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4894                    }
4895                    break;
4896                case R.styleable.View_overScrollMode:
4897                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4898                    break;
4899                case R.styleable.View_verticalScrollbarPosition:
4900                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4901                    break;
4902                case R.styleable.View_layerType:
4903                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4904                    break;
4905                case R.styleable.View_textDirection:
4906                    // Clear any text direction flag already set
4907                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4908                    // Set the text direction flags depending on the value of the attribute
4909                    final int textDirection = a.getInt(attr, -1);
4910                    if (textDirection != -1) {
4911                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4912                    }
4913                    break;
4914                case R.styleable.View_textAlignment:
4915                    // Clear any text alignment flag already set
4916                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4917                    // Set the text alignment flag depending on the value of the attribute
4918                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4919                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4920                    break;
4921                case R.styleable.View_importantForAccessibility:
4922                    setImportantForAccessibility(a.getInt(attr,
4923                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4924                    break;
4925                case R.styleable.View_accessibilityLiveRegion:
4926                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4927                    break;
4928                case R.styleable.View_transitionName:
4929                    setTransitionName(a.getString(attr));
4930                    break;
4931                case R.styleable.View_nestedScrollingEnabled:
4932                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4933                    break;
4934                case R.styleable.View_stateListAnimator:
4935                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4936                            a.getResourceId(attr, 0)));
4937                    break;
4938                case R.styleable.View_backgroundTint:
4939                    // This will get applied later during setBackground().
4940                    if (mBackgroundTint == null) {
4941                        mBackgroundTint = new TintInfo();
4942                    }
4943                    mBackgroundTint.mTintList = a.getColorStateList(
4944                            R.styleable.View_backgroundTint);
4945                    mBackgroundTint.mHasTintList = true;
4946                    break;
4947                case R.styleable.View_backgroundTintMode:
4948                    // This will get applied later during setBackground().
4949                    if (mBackgroundTint == null) {
4950                        mBackgroundTint = new TintInfo();
4951                    }
4952                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4953                            R.styleable.View_backgroundTintMode, -1), null);
4954                    mBackgroundTint.mHasTintMode = true;
4955                    break;
4956                case R.styleable.View_outlineProvider:
4957                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4958                            PROVIDER_BACKGROUND));
4959                    break;
4960                case R.styleable.View_foreground:
4961                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4962                        setForeground(a.getDrawable(attr));
4963                    }
4964                    break;
4965                case R.styleable.View_foregroundGravity:
4966                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4967                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4968                    }
4969                    break;
4970                case R.styleable.View_foregroundTintMode:
4971                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4972                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4973                    }
4974                    break;
4975                case R.styleable.View_foregroundTint:
4976                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4977                        setForegroundTintList(a.getColorStateList(attr));
4978                    }
4979                    break;
4980                case R.styleable.View_foregroundInsidePadding:
4981                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
4982                        if (mForegroundInfo == null) {
4983                            mForegroundInfo = new ForegroundInfo();
4984                        }
4985                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4986                                mForegroundInfo.mInsidePadding);
4987                    }
4988                    break;
4989                case R.styleable.View_scrollIndicators:
4990                    final int scrollIndicators =
4991                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4992                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4993                    if (scrollIndicators != 0) {
4994                        mPrivateFlags3 |= scrollIndicators;
4995                        initializeScrollIndicators = true;
4996                    }
4997                    break;
4998                case R.styleable.View_pointerIcon:
4999                    final int resourceId = a.getResourceId(attr, 0);
5000                    if (resourceId != 0) {
5001                        setPointerIcon(PointerIcon.load(
5002                                context.getResources(), resourceId));
5003                    } else {
5004                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5005                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5006                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5007                        }
5008                    }
5009                    break;
5010                case R.styleable.View_forceHasOverlappingRendering:
5011                    if (a.peekValue(attr) != null) {
5012                        forceHasOverlappingRendering(a.getBoolean(attr, true));
5013                    }
5014                    break;
5015                case R.styleable.View_tooltipText:
5016                    setTooltipText(a.getText(attr));
5017                    break;
5018                case R.styleable.View_keyboardNavigationCluster:
5019                    if (a.peekValue(attr) != null) {
5020                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
5021                    }
5022                    break;
5023                case R.styleable.View_focusedByDefault:
5024                    if (a.peekValue(attr) != null) {
5025                        setFocusedByDefault(a.getBoolean(attr, true));
5026                    }
5027                    break;
5028                case R.styleable.View_autofillHints:
5029                    if (a.peekValue(attr) != null) {
5030                        CharSequence[] rawHints = null;
5031                        String rawString = null;
5032
5033                        if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5034                            int resId = a.getResourceId(attr, 0);
5035
5036                            try {
5037                                rawHints = a.getTextArray(attr);
5038                            } catch (Resources.NotFoundException e) {
5039                                rawString = getResources().getString(resId);
5040                            }
5041                        } else {
5042                            rawString = a.getString(attr);
5043                        }
5044
5045                        if (rawHints == null) {
5046                            if (rawString == null) {
5047                                throw new IllegalArgumentException(
5048                                        "Could not resolve autofillHints");
5049                            } else {
5050                                rawHints = rawString.split(",");
5051                            }
5052                        }
5053
5054                        String[] hints = new String[rawHints.length];
5055
5056                        int numHints = rawHints.length;
5057                        for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5058                            hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5059                        }
5060                        setAutofillHints(hints);
5061                    }
5062                    break;
5063                case R.styleable.View_importantForAutofill:
5064                    if (a.peekValue(attr) != null) {
5065                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5066                    }
5067                    break;
5068                case R.styleable.View_defaultFocusHighlightEnabled:
5069                    if (a.peekValue(attr) != null) {
5070                        setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5071                    }
5072                    break;
5073            }
5074        }
5075
5076        setOverScrollMode(overScrollMode);
5077
5078        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5079        // the resolved layout direction). Those cached values will be used later during padding
5080        // resolution.
5081        mUserPaddingStart = startPadding;
5082        mUserPaddingEnd = endPadding;
5083
5084        if (background != null) {
5085            setBackground(background);
5086        }
5087
5088        // setBackground above will record that padding is currently provided by the background.
5089        // If we have padding specified via xml, record that here instead and use it.
5090        mLeftPaddingDefined = leftPaddingDefined;
5091        mRightPaddingDefined = rightPaddingDefined;
5092
5093        if (padding >= 0) {
5094            leftPadding = padding;
5095            topPadding = padding;
5096            rightPadding = padding;
5097            bottomPadding = padding;
5098            mUserPaddingLeftInitial = padding;
5099            mUserPaddingRightInitial = padding;
5100        } else {
5101            if (paddingHorizontal >= 0) {
5102                leftPadding = paddingHorizontal;
5103                rightPadding = paddingHorizontal;
5104                mUserPaddingLeftInitial = paddingHorizontal;
5105                mUserPaddingRightInitial = paddingHorizontal;
5106            }
5107            if (paddingVertical >= 0) {
5108                topPadding = paddingVertical;
5109                bottomPadding = paddingVertical;
5110            }
5111        }
5112
5113        if (isRtlCompatibilityMode()) {
5114            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5115            // left / right padding are used if defined (meaning here nothing to do). If they are not
5116            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5117            // start / end and resolve them as left / right (layout direction is not taken into account).
5118            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5119            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5120            // defined.
5121            if (!mLeftPaddingDefined && startPaddingDefined) {
5122                leftPadding = startPadding;
5123            }
5124            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5125            if (!mRightPaddingDefined && endPaddingDefined) {
5126                rightPadding = endPadding;
5127            }
5128            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5129        } else {
5130            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5131            // values defined. Otherwise, left /right values are used.
5132            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5133            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5134            // defined.
5135            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5136
5137            if (mLeftPaddingDefined && !hasRelativePadding) {
5138                mUserPaddingLeftInitial = leftPadding;
5139            }
5140            if (mRightPaddingDefined && !hasRelativePadding) {
5141                mUserPaddingRightInitial = rightPadding;
5142            }
5143        }
5144
5145        internalSetPadding(
5146                mUserPaddingLeftInitial,
5147                topPadding >= 0 ? topPadding : mPaddingTop,
5148                mUserPaddingRightInitial,
5149                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5150
5151        if (viewFlagMasks != 0) {
5152            setFlags(viewFlagValues, viewFlagMasks);
5153        }
5154
5155        if (initializeScrollbars) {
5156            initializeScrollbarsInternal(a);
5157        }
5158
5159        if (initializeScrollIndicators) {
5160            initializeScrollIndicatorsInternal();
5161        }
5162
5163        a.recycle();
5164
5165        // Needs to be called after mViewFlags is set
5166        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5167            recomputePadding();
5168        }
5169
5170        if (x != 0 || y != 0) {
5171            scrollTo(x, y);
5172        }
5173
5174        if (transformSet) {
5175            setTranslationX(tx);
5176            setTranslationY(ty);
5177            setTranslationZ(tz);
5178            setElevation(elevation);
5179            setRotation(rotation);
5180            setRotationX(rotationX);
5181            setRotationY(rotationY);
5182            setScaleX(sx);
5183            setScaleY(sy);
5184        }
5185
5186        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5187            setScrollContainer(true);
5188        }
5189
5190        computeOpaqueFlags();
5191    }
5192
5193    /**
5194     * An implementation of OnClickListener that attempts to lazily load a
5195     * named click handling method from a parent or ancestor context.
5196     */
5197    private static class DeclaredOnClickListener implements OnClickListener {
5198        private final View mHostView;
5199        private final String mMethodName;
5200
5201        private Method mResolvedMethod;
5202        private Context mResolvedContext;
5203
5204        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5205            mHostView = hostView;
5206            mMethodName = methodName;
5207        }
5208
5209        @Override
5210        public void onClick(@NonNull View v) {
5211            if (mResolvedMethod == null) {
5212                resolveMethod(mHostView.getContext(), mMethodName);
5213            }
5214
5215            try {
5216                mResolvedMethod.invoke(mResolvedContext, v);
5217            } catch (IllegalAccessException e) {
5218                throw new IllegalStateException(
5219                        "Could not execute non-public method for android:onClick", e);
5220            } catch (InvocationTargetException e) {
5221                throw new IllegalStateException(
5222                        "Could not execute method for android:onClick", e);
5223            }
5224        }
5225
5226        @NonNull
5227        private void resolveMethod(@Nullable Context context, @NonNull String name) {
5228            while (context != null) {
5229                try {
5230                    if (!context.isRestricted()) {
5231                        final Method method = context.getClass().getMethod(mMethodName, View.class);
5232                        if (method != null) {
5233                            mResolvedMethod = method;
5234                            mResolvedContext = context;
5235                            return;
5236                        }
5237                    }
5238                } catch (NoSuchMethodException e) {
5239                    // Failed to find method, keep searching up the hierarchy.
5240                }
5241
5242                if (context instanceof ContextWrapper) {
5243                    context = ((ContextWrapper) context).getBaseContext();
5244                } else {
5245                    // Can't search up the hierarchy, null out and fail.
5246                    context = null;
5247                }
5248            }
5249
5250            final int id = mHostView.getId();
5251            final String idText = id == NO_ID ? "" : " with id '"
5252                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5253            throw new IllegalStateException("Could not find method " + mMethodName
5254                    + "(View) in a parent or ancestor Context for android:onClick "
5255                    + "attribute defined on view " + mHostView.getClass() + idText);
5256        }
5257    }
5258
5259    /**
5260     * Non-public constructor for use in testing
5261     */
5262    View() {
5263        mResources = null;
5264        mRenderNode = RenderNode.create(getClass().getName(), this);
5265    }
5266
5267    final boolean debugDraw() {
5268        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5269    }
5270
5271    private static SparseArray<String> getAttributeMap() {
5272        if (mAttributeMap == null) {
5273            mAttributeMap = new SparseArray<>();
5274        }
5275        return mAttributeMap;
5276    }
5277
5278    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5279        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5280        final int indexCount = t.getIndexCount();
5281        final String[] attributes = new String[(attrsCount + indexCount) * 2];
5282
5283        int i = 0;
5284
5285        // Store raw XML attributes.
5286        for (int j = 0; j < attrsCount; ++j) {
5287            attributes[i] = attrs.getAttributeName(j);
5288            attributes[i + 1] = attrs.getAttributeValue(j);
5289            i += 2;
5290        }
5291
5292        // Store resolved styleable attributes.
5293        final Resources res = t.getResources();
5294        final SparseArray<String> attributeMap = getAttributeMap();
5295        for (int j = 0; j < indexCount; ++j) {
5296            final int index = t.getIndex(j);
5297            if (!t.hasValueOrEmpty(index)) {
5298                // Value is undefined. Skip it.
5299                continue;
5300            }
5301
5302            final int resourceId = t.getResourceId(index, 0);
5303            if (resourceId == 0) {
5304                // Value is not a reference. Skip it.
5305                continue;
5306            }
5307
5308            String resourceName = attributeMap.get(resourceId);
5309            if (resourceName == null) {
5310                try {
5311                    resourceName = res.getResourceName(resourceId);
5312                } catch (Resources.NotFoundException e) {
5313                    resourceName = "0x" + Integer.toHexString(resourceId);
5314                }
5315                attributeMap.put(resourceId, resourceName);
5316            }
5317
5318            attributes[i] = resourceName;
5319            attributes[i + 1] = t.getString(index);
5320            i += 2;
5321        }
5322
5323        // Trim to fit contents.
5324        final String[] trimmed = new String[i];
5325        System.arraycopy(attributes, 0, trimmed, 0, i);
5326        mAttributes = trimmed;
5327    }
5328
5329    public String toString() {
5330        StringBuilder out = new StringBuilder(128);
5331        out.append(getClass().getName());
5332        out.append('{');
5333        out.append(Integer.toHexString(System.identityHashCode(this)));
5334        out.append(' ');
5335        switch (mViewFlags&VISIBILITY_MASK) {
5336            case VISIBLE: out.append('V'); break;
5337            case INVISIBLE: out.append('I'); break;
5338            case GONE: out.append('G'); break;
5339            default: out.append('.'); break;
5340        }
5341        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5342        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5343        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5344        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5345        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5346        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5347        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5348        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5349        out.append(' ');
5350        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5351        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5352        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5353        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5354            out.append('p');
5355        } else {
5356            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5357        }
5358        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5359        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5360        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5361        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5362        out.append(' ');
5363        out.append(mLeft);
5364        out.append(',');
5365        out.append(mTop);
5366        out.append('-');
5367        out.append(mRight);
5368        out.append(',');
5369        out.append(mBottom);
5370        final int id = getId();
5371        if (id != NO_ID) {
5372            out.append(" #");
5373            out.append(Integer.toHexString(id));
5374            final Resources r = mResources;
5375            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5376                try {
5377                    String pkgname;
5378                    switch (id&0xff000000) {
5379                        case 0x7f000000:
5380                            pkgname="app";
5381                            break;
5382                        case 0x01000000:
5383                            pkgname="android";
5384                            break;
5385                        default:
5386                            pkgname = r.getResourcePackageName(id);
5387                            break;
5388                    }
5389                    String typename = r.getResourceTypeName(id);
5390                    String entryname = r.getResourceEntryName(id);
5391                    out.append(" ");
5392                    out.append(pkgname);
5393                    out.append(":");
5394                    out.append(typename);
5395                    out.append("/");
5396                    out.append(entryname);
5397                } catch (Resources.NotFoundException e) {
5398                }
5399            }
5400        }
5401        out.append("}");
5402        return out.toString();
5403    }
5404
5405    /**
5406     * <p>
5407     * Initializes the fading edges from a given set of styled attributes. This
5408     * method should be called by subclasses that need fading edges and when an
5409     * instance of these subclasses is created programmatically rather than
5410     * being inflated from XML. This method is automatically called when the XML
5411     * is inflated.
5412     * </p>
5413     *
5414     * @param a the styled attributes set to initialize the fading edges from
5415     *
5416     * @removed
5417     */
5418    protected void initializeFadingEdge(TypedArray a) {
5419        // This method probably shouldn't have been included in the SDK to begin with.
5420        // It relies on 'a' having been initialized using an attribute filter array that is
5421        // not publicly available to the SDK. The old method has been renamed
5422        // to initializeFadingEdgeInternal and hidden for framework use only;
5423        // this one initializes using defaults to make it safe to call for apps.
5424
5425        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5426
5427        initializeFadingEdgeInternal(arr);
5428
5429        arr.recycle();
5430    }
5431
5432    /**
5433     * <p>
5434     * Initializes the fading edges from a given set of styled attributes. This
5435     * method should be called by subclasses that need fading edges and when an
5436     * instance of these subclasses is created programmatically rather than
5437     * being inflated from XML. This method is automatically called when the XML
5438     * is inflated.
5439     * </p>
5440     *
5441     * @param a the styled attributes set to initialize the fading edges from
5442     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5443     */
5444    protected void initializeFadingEdgeInternal(TypedArray a) {
5445        initScrollCache();
5446
5447        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5448                R.styleable.View_fadingEdgeLength,
5449                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5450    }
5451
5452    /**
5453     * Returns the size of the vertical faded edges used to indicate that more
5454     * content in this view is visible.
5455     *
5456     * @return The size in pixels of the vertical faded edge or 0 if vertical
5457     *         faded edges are not enabled for this view.
5458     * @attr ref android.R.styleable#View_fadingEdgeLength
5459     */
5460    public int getVerticalFadingEdgeLength() {
5461        if (isVerticalFadingEdgeEnabled()) {
5462            ScrollabilityCache cache = mScrollCache;
5463            if (cache != null) {
5464                return cache.fadingEdgeLength;
5465            }
5466        }
5467        return 0;
5468    }
5469
5470    /**
5471     * Set the size of the faded edge used to indicate that more content in this
5472     * view is available.  Will not change whether the fading edge is enabled; use
5473     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5474     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5475     * for the vertical or horizontal fading edges.
5476     *
5477     * @param length The size in pixels of the faded edge used to indicate that more
5478     *        content in this view is visible.
5479     */
5480    public void setFadingEdgeLength(int length) {
5481        initScrollCache();
5482        mScrollCache.fadingEdgeLength = length;
5483    }
5484
5485    /**
5486     * Returns the size of the horizontal faded edges used to indicate that more
5487     * content in this view is visible.
5488     *
5489     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5490     *         faded edges are not enabled for this view.
5491     * @attr ref android.R.styleable#View_fadingEdgeLength
5492     */
5493    public int getHorizontalFadingEdgeLength() {
5494        if (isHorizontalFadingEdgeEnabled()) {
5495            ScrollabilityCache cache = mScrollCache;
5496            if (cache != null) {
5497                return cache.fadingEdgeLength;
5498            }
5499        }
5500        return 0;
5501    }
5502
5503    /**
5504     * Returns the width of the vertical scrollbar.
5505     *
5506     * @return The width in pixels of the vertical scrollbar or 0 if there
5507     *         is no vertical scrollbar.
5508     */
5509    public int getVerticalScrollbarWidth() {
5510        ScrollabilityCache cache = mScrollCache;
5511        if (cache != null) {
5512            ScrollBarDrawable scrollBar = cache.scrollBar;
5513            if (scrollBar != null) {
5514                int size = scrollBar.getSize(true);
5515                if (size <= 0) {
5516                    size = cache.scrollBarSize;
5517                }
5518                return size;
5519            }
5520            return 0;
5521        }
5522        return 0;
5523    }
5524
5525    /**
5526     * Returns the height of the horizontal scrollbar.
5527     *
5528     * @return The height in pixels of the horizontal scrollbar or 0 if
5529     *         there is no horizontal scrollbar.
5530     */
5531    protected int getHorizontalScrollbarHeight() {
5532        ScrollabilityCache cache = mScrollCache;
5533        if (cache != null) {
5534            ScrollBarDrawable scrollBar = cache.scrollBar;
5535            if (scrollBar != null) {
5536                int size = scrollBar.getSize(false);
5537                if (size <= 0) {
5538                    size = cache.scrollBarSize;
5539                }
5540                return size;
5541            }
5542            return 0;
5543        }
5544        return 0;
5545    }
5546
5547    /**
5548     * <p>
5549     * Initializes the scrollbars from a given set of styled attributes. This
5550     * method should be called by subclasses that need scrollbars and when an
5551     * instance of these subclasses is created programmatically rather than
5552     * being inflated from XML. This method is automatically called when the XML
5553     * is inflated.
5554     * </p>
5555     *
5556     * @param a the styled attributes set to initialize the scrollbars from
5557     *
5558     * @removed
5559     */
5560    protected void initializeScrollbars(TypedArray a) {
5561        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5562        // using the View filter array which is not available to the SDK. As such, internal
5563        // framework usage now uses initializeScrollbarsInternal and we grab a default
5564        // TypedArray with the right filter instead here.
5565        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5566
5567        initializeScrollbarsInternal(arr);
5568
5569        // We ignored the method parameter. Recycle the one we actually did use.
5570        arr.recycle();
5571    }
5572
5573    /**
5574     * <p>
5575     * Initializes the scrollbars from a given set of styled attributes. This
5576     * method should be called by subclasses that need scrollbars and when an
5577     * instance of these subclasses is created programmatically rather than
5578     * being inflated from XML. This method is automatically called when the XML
5579     * is inflated.
5580     * </p>
5581     *
5582     * @param a the styled attributes set to initialize the scrollbars from
5583     * @hide
5584     */
5585    protected void initializeScrollbarsInternal(TypedArray a) {
5586        initScrollCache();
5587
5588        final ScrollabilityCache scrollabilityCache = mScrollCache;
5589
5590        if (scrollabilityCache.scrollBar == null) {
5591            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5592            scrollabilityCache.scrollBar.setState(getDrawableState());
5593            scrollabilityCache.scrollBar.setCallback(this);
5594        }
5595
5596        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5597
5598        if (!fadeScrollbars) {
5599            scrollabilityCache.state = ScrollabilityCache.ON;
5600        }
5601        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5602
5603
5604        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5605                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5606                        .getScrollBarFadeDuration());
5607        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5608                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5609                ViewConfiguration.getScrollDefaultDelay());
5610
5611
5612        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5613                com.android.internal.R.styleable.View_scrollbarSize,
5614                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5615
5616        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5617        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5618
5619        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5620        if (thumb != null) {
5621            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5622        }
5623
5624        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5625                false);
5626        if (alwaysDraw) {
5627            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5628        }
5629
5630        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5631        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5632
5633        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5634        if (thumb != null) {
5635            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5636        }
5637
5638        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5639                false);
5640        if (alwaysDraw) {
5641            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5642        }
5643
5644        // Apply layout direction to the new Drawables if needed
5645        final int layoutDirection = getLayoutDirection();
5646        if (track != null) {
5647            track.setLayoutDirection(layoutDirection);
5648        }
5649        if (thumb != null) {
5650            thumb.setLayoutDirection(layoutDirection);
5651        }
5652
5653        // Re-apply user/background padding so that scrollbar(s) get added
5654        resolvePadding();
5655    }
5656
5657    private void initializeScrollIndicatorsInternal() {
5658        // Some day maybe we'll break this into top/left/start/etc. and let the
5659        // client control it. Until then, you can have any scroll indicator you
5660        // want as long as it's a 1dp foreground-colored rectangle.
5661        if (mScrollIndicatorDrawable == null) {
5662            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5663        }
5664    }
5665
5666    /**
5667     * <p>
5668     * Initalizes the scrollability cache if necessary.
5669     * </p>
5670     */
5671    private void initScrollCache() {
5672        if (mScrollCache == null) {
5673            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5674        }
5675    }
5676
5677    private ScrollabilityCache getScrollCache() {
5678        initScrollCache();
5679        return mScrollCache;
5680    }
5681
5682    /**
5683     * Set the position of the vertical scroll bar. Should be one of
5684     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5685     * {@link #SCROLLBAR_POSITION_RIGHT}.
5686     *
5687     * @param position Where the vertical scroll bar should be positioned.
5688     */
5689    public void setVerticalScrollbarPosition(int position) {
5690        if (mVerticalScrollbarPosition != position) {
5691            mVerticalScrollbarPosition = position;
5692            computeOpaqueFlags();
5693            resolvePadding();
5694        }
5695    }
5696
5697    /**
5698     * @return The position where the vertical scroll bar will show, if applicable.
5699     * @see #setVerticalScrollbarPosition(int)
5700     */
5701    public int getVerticalScrollbarPosition() {
5702        return mVerticalScrollbarPosition;
5703    }
5704
5705    boolean isOnScrollbar(float x, float y) {
5706        if (mScrollCache == null) {
5707            return false;
5708        }
5709        x += getScrollX();
5710        y += getScrollY();
5711        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5712            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5713            getVerticalScrollBarBounds(null, touchBounds);
5714            if (touchBounds.contains((int) x, (int) y)) {
5715                return true;
5716            }
5717        }
5718        if (isHorizontalScrollBarEnabled()) {
5719            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5720            getHorizontalScrollBarBounds(null, touchBounds);
5721            if (touchBounds.contains((int) x, (int) y)) {
5722                return true;
5723            }
5724        }
5725        return false;
5726    }
5727
5728    boolean isOnScrollbarThumb(float x, float y) {
5729        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5730    }
5731
5732    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5733        if (mScrollCache == null) {
5734            return false;
5735        }
5736        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5737            x += getScrollX();
5738            y += getScrollY();
5739            final Rect bounds = mScrollCache.mScrollBarBounds;
5740            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5741            getVerticalScrollBarBounds(bounds, touchBounds);
5742            final int range = computeVerticalScrollRange();
5743            final int offset = computeVerticalScrollOffset();
5744            final int extent = computeVerticalScrollExtent();
5745            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5746                    extent, range);
5747            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5748                    extent, range, offset);
5749            final int thumbTop = bounds.top + thumbOffset;
5750            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5751            if (x >= touchBounds.left && x <= touchBounds.right
5752                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5753                return true;
5754            }
5755        }
5756        return false;
5757    }
5758
5759    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5760        if (mScrollCache == null) {
5761            return false;
5762        }
5763        if (isHorizontalScrollBarEnabled()) {
5764            x += getScrollX();
5765            y += getScrollY();
5766            final Rect bounds = mScrollCache.mScrollBarBounds;
5767            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5768            getHorizontalScrollBarBounds(bounds, touchBounds);
5769            final int range = computeHorizontalScrollRange();
5770            final int offset = computeHorizontalScrollOffset();
5771            final int extent = computeHorizontalScrollExtent();
5772            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5773                    extent, range);
5774            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5775                    extent, range, offset);
5776            final int thumbLeft = bounds.left + thumbOffset;
5777            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5778            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5779                    && y >= touchBounds.top && y <= touchBounds.bottom) {
5780                return true;
5781            }
5782        }
5783        return false;
5784    }
5785
5786    boolean isDraggingScrollBar() {
5787        return mScrollCache != null
5788                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5789    }
5790
5791    /**
5792     * Sets the state of all scroll indicators.
5793     * <p>
5794     * See {@link #setScrollIndicators(int, int)} for usage information.
5795     *
5796     * @param indicators a bitmask of indicators that should be enabled, or
5797     *                   {@code 0} to disable all indicators
5798     * @see #setScrollIndicators(int, int)
5799     * @see #getScrollIndicators()
5800     * @attr ref android.R.styleable#View_scrollIndicators
5801     */
5802    public void setScrollIndicators(@ScrollIndicators int indicators) {
5803        setScrollIndicators(indicators,
5804                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5805    }
5806
5807    /**
5808     * Sets the state of the scroll indicators specified by the mask. To change
5809     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5810     * <p>
5811     * When a scroll indicator is enabled, it will be displayed if the view
5812     * can scroll in the direction of the indicator.
5813     * <p>
5814     * Multiple indicator types may be enabled or disabled by passing the
5815     * logical OR of the desired types. If multiple types are specified, they
5816     * will all be set to the same enabled state.
5817     * <p>
5818     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5819     *
5820     * @param indicators the indicator direction, or the logical OR of multiple
5821     *             indicator directions. One or more of:
5822     *             <ul>
5823     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5824     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5825     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5826     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5827     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5828     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5829     *             </ul>
5830     * @see #setScrollIndicators(int)
5831     * @see #getScrollIndicators()
5832     * @attr ref android.R.styleable#View_scrollIndicators
5833     */
5834    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5835        // Shift and sanitize mask.
5836        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5837        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5838
5839        // Shift and mask indicators.
5840        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5841        indicators &= mask;
5842
5843        // Merge with non-masked flags.
5844        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5845
5846        if (mPrivateFlags3 != updatedFlags) {
5847            mPrivateFlags3 = updatedFlags;
5848
5849            if (indicators != 0) {
5850                initializeScrollIndicatorsInternal();
5851            }
5852            invalidate();
5853        }
5854    }
5855
5856    /**
5857     * Returns a bitmask representing the enabled scroll indicators.
5858     * <p>
5859     * For example, if the top and left scroll indicators are enabled and all
5860     * other indicators are disabled, the return value will be
5861     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5862     * <p>
5863     * To check whether the bottom scroll indicator is enabled, use the value
5864     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5865     *
5866     * @return a bitmask representing the enabled scroll indicators
5867     */
5868    @ScrollIndicators
5869    public int getScrollIndicators() {
5870        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5871                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5872    }
5873
5874    ListenerInfo getListenerInfo() {
5875        if (mListenerInfo != null) {
5876            return mListenerInfo;
5877        }
5878        mListenerInfo = new ListenerInfo();
5879        return mListenerInfo;
5880    }
5881
5882    /**
5883     * Register a callback to be invoked when the scroll X or Y positions of
5884     * this view change.
5885     * <p>
5886     * <b>Note:</b> Some views handle scrolling independently from View and may
5887     * have their own separate listeners for scroll-type events. For example,
5888     * {@link android.widget.ListView ListView} allows clients to register an
5889     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5890     * to listen for changes in list scroll position.
5891     *
5892     * @param l The listener to notify when the scroll X or Y position changes.
5893     * @see android.view.View#getScrollX()
5894     * @see android.view.View#getScrollY()
5895     */
5896    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5897        getListenerInfo().mOnScrollChangeListener = l;
5898    }
5899
5900    /**
5901     * Register a callback to be invoked when focus of this view changed.
5902     *
5903     * @param l The callback that will run.
5904     */
5905    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5906        getListenerInfo().mOnFocusChangeListener = l;
5907    }
5908
5909    /**
5910     * Add a listener that will be called when the bounds of the view change due to
5911     * layout processing.
5912     *
5913     * @param listener The listener that will be called when layout bounds change.
5914     */
5915    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5916        ListenerInfo li = getListenerInfo();
5917        if (li.mOnLayoutChangeListeners == null) {
5918            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5919        }
5920        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5921            li.mOnLayoutChangeListeners.add(listener);
5922        }
5923    }
5924
5925    /**
5926     * Remove a listener for layout changes.
5927     *
5928     * @param listener The listener for layout bounds change.
5929     */
5930    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5931        ListenerInfo li = mListenerInfo;
5932        if (li == null || li.mOnLayoutChangeListeners == null) {
5933            return;
5934        }
5935        li.mOnLayoutChangeListeners.remove(listener);
5936    }
5937
5938    /**
5939     * Add a listener for attach state changes.
5940     *
5941     * This listener will be called whenever this view is attached or detached
5942     * from a window. Remove the listener using
5943     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5944     *
5945     * @param listener Listener to attach
5946     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5947     */
5948    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5949        ListenerInfo li = getListenerInfo();
5950        if (li.mOnAttachStateChangeListeners == null) {
5951            li.mOnAttachStateChangeListeners
5952                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5953        }
5954        li.mOnAttachStateChangeListeners.add(listener);
5955    }
5956
5957    /**
5958     * Remove a listener for attach state changes. The listener will receive no further
5959     * notification of window attach/detach events.
5960     *
5961     * @param listener Listener to remove
5962     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5963     */
5964    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5965        ListenerInfo li = mListenerInfo;
5966        if (li == null || li.mOnAttachStateChangeListeners == null) {
5967            return;
5968        }
5969        li.mOnAttachStateChangeListeners.remove(listener);
5970    }
5971
5972    /**
5973     * Returns the focus-change callback registered for this view.
5974     *
5975     * @return The callback, or null if one is not registered.
5976     */
5977    public OnFocusChangeListener getOnFocusChangeListener() {
5978        ListenerInfo li = mListenerInfo;
5979        return li != null ? li.mOnFocusChangeListener : null;
5980    }
5981
5982    /**
5983     * Register a callback to be invoked when this view is clicked. If this view is not
5984     * clickable, it becomes clickable.
5985     *
5986     * @param l The callback that will run
5987     *
5988     * @see #setClickable(boolean)
5989     */
5990    public void setOnClickListener(@Nullable OnClickListener l) {
5991        if (!isClickable()) {
5992            setClickable(true);
5993        }
5994        getListenerInfo().mOnClickListener = l;
5995    }
5996
5997    /**
5998     * Return whether this view has an attached OnClickListener.  Returns
5999     * true if there is a listener, false if there is none.
6000     */
6001    public boolean hasOnClickListeners() {
6002        ListenerInfo li = mListenerInfo;
6003        return (li != null && li.mOnClickListener != null);
6004    }
6005
6006    /**
6007     * Register a callback to be invoked when this view is clicked and held. If this view is not
6008     * long clickable, it becomes long clickable.
6009     *
6010     * @param l The callback that will run
6011     *
6012     * @see #setLongClickable(boolean)
6013     */
6014    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6015        if (!isLongClickable()) {
6016            setLongClickable(true);
6017        }
6018        getListenerInfo().mOnLongClickListener = l;
6019    }
6020
6021    /**
6022     * Register a callback to be invoked when this view is context clicked. If the view is not
6023     * context clickable, it becomes context clickable.
6024     *
6025     * @param l The callback that will run
6026     * @see #setContextClickable(boolean)
6027     */
6028    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6029        if (!isContextClickable()) {
6030            setContextClickable(true);
6031        }
6032        getListenerInfo().mOnContextClickListener = l;
6033    }
6034
6035    /**
6036     * Register a callback to be invoked when the context menu for this view is
6037     * being built. If this view is not long clickable, it becomes long clickable.
6038     *
6039     * @param l The callback that will run
6040     *
6041     */
6042    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6043        if (!isLongClickable()) {
6044            setLongClickable(true);
6045        }
6046        getListenerInfo().mOnCreateContextMenuListener = l;
6047    }
6048
6049    /**
6050     * Set an observer to collect stats for each frame rendered for this view.
6051     *
6052     * @hide
6053     */
6054    public void addFrameMetricsListener(Window window,
6055            Window.OnFrameMetricsAvailableListener listener,
6056            Handler handler) {
6057        if (mAttachInfo != null) {
6058            if (mAttachInfo.mThreadedRenderer != null) {
6059                if (mFrameMetricsObservers == null) {
6060                    mFrameMetricsObservers = new ArrayList<>();
6061                }
6062
6063                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6064                        handler.getLooper(), listener);
6065                mFrameMetricsObservers.add(fmo);
6066                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6067            } else {
6068                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6069            }
6070        } else {
6071            if (mFrameMetricsObservers == null) {
6072                mFrameMetricsObservers = new ArrayList<>();
6073            }
6074
6075            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6076                    handler.getLooper(), listener);
6077            mFrameMetricsObservers.add(fmo);
6078        }
6079    }
6080
6081    /**
6082     * Remove observer configured to collect frame stats for this view.
6083     *
6084     * @hide
6085     */
6086    public void removeFrameMetricsListener(
6087            Window.OnFrameMetricsAvailableListener listener) {
6088        ThreadedRenderer renderer = getThreadedRenderer();
6089        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6090        if (fmo == null) {
6091            throw new IllegalArgumentException(
6092                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
6093        }
6094
6095        if (mFrameMetricsObservers != null) {
6096            mFrameMetricsObservers.remove(fmo);
6097            if (renderer != null) {
6098                renderer.removeFrameMetricsObserver(fmo);
6099            }
6100        }
6101    }
6102
6103    private void registerPendingFrameMetricsObservers() {
6104        if (mFrameMetricsObservers != null) {
6105            ThreadedRenderer renderer = getThreadedRenderer();
6106            if (renderer != null) {
6107                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6108                    renderer.addFrameMetricsObserver(fmo);
6109                }
6110            } else {
6111                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6112            }
6113        }
6114    }
6115
6116    private FrameMetricsObserver findFrameMetricsObserver(
6117            Window.OnFrameMetricsAvailableListener listener) {
6118        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6119            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6120            if (observer.mListener == listener) {
6121                return observer;
6122            }
6123        }
6124
6125        return null;
6126    }
6127
6128    /**
6129     * Call this view's OnClickListener, if it is defined.  Performs all normal
6130     * actions associated with clicking: reporting accessibility event, playing
6131     * a sound, etc.
6132     *
6133     * @return True there was an assigned OnClickListener that was called, false
6134     *         otherwise is returned.
6135     */
6136    public boolean performClick() {
6137        final boolean result;
6138        final ListenerInfo li = mListenerInfo;
6139        if (li != null && li.mOnClickListener != null) {
6140            playSoundEffect(SoundEffectConstants.CLICK);
6141            li.mOnClickListener.onClick(this);
6142            result = true;
6143        } else {
6144            result = false;
6145        }
6146
6147        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6148
6149        notifyEnterOrExitForAutoFillIfNeeded(true);
6150
6151        return result;
6152    }
6153
6154    /**
6155     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6156     * this only calls the listener, and does not do any associated clicking
6157     * actions like reporting an accessibility event.
6158     *
6159     * @return True there was an assigned OnClickListener that was called, false
6160     *         otherwise is returned.
6161     */
6162    public boolean callOnClick() {
6163        ListenerInfo li = mListenerInfo;
6164        if (li != null && li.mOnClickListener != null) {
6165            li.mOnClickListener.onClick(this);
6166            return true;
6167        }
6168        return false;
6169    }
6170
6171    /**
6172     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6173     * context menu if the OnLongClickListener did not consume the event.
6174     *
6175     * @return {@code true} if one of the above receivers consumed the event,
6176     *         {@code false} otherwise
6177     */
6178    public boolean performLongClick() {
6179        return performLongClickInternal(mLongClickX, mLongClickY);
6180    }
6181
6182    /**
6183     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6184     * context menu if the OnLongClickListener did not consume the event,
6185     * anchoring it to an (x,y) coordinate.
6186     *
6187     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6188     *          to disable anchoring
6189     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6190     *          to disable anchoring
6191     * @return {@code true} if one of the above receivers consumed the event,
6192     *         {@code false} otherwise
6193     */
6194    public boolean performLongClick(float x, float y) {
6195        mLongClickX = x;
6196        mLongClickY = y;
6197        final boolean handled = performLongClick();
6198        mLongClickX = Float.NaN;
6199        mLongClickY = Float.NaN;
6200        return handled;
6201    }
6202
6203    /**
6204     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6205     * context menu if the OnLongClickListener did not consume the event,
6206     * optionally anchoring it to an (x,y) coordinate.
6207     *
6208     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6209     *          to disable anchoring
6210     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6211     *          to disable anchoring
6212     * @return {@code true} if one of the above receivers consumed the event,
6213     *         {@code false} otherwise
6214     */
6215    private boolean performLongClickInternal(float x, float y) {
6216        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6217
6218        boolean handled = false;
6219        final ListenerInfo li = mListenerInfo;
6220        if (li != null && li.mOnLongClickListener != null) {
6221            handled = li.mOnLongClickListener.onLongClick(View.this);
6222        }
6223        if (!handled) {
6224            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6225            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6226        }
6227        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6228            if (!handled) {
6229                handled = showLongClickTooltip((int) x, (int) y);
6230            }
6231        }
6232        if (handled) {
6233            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6234        }
6235        return handled;
6236    }
6237
6238    /**
6239     * Call this view's OnContextClickListener, if it is defined.
6240     *
6241     * @param x the x coordinate of the context click
6242     * @param y the y coordinate of the context click
6243     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6244     *         otherwise.
6245     */
6246    public boolean performContextClick(float x, float y) {
6247        return performContextClick();
6248    }
6249
6250    /**
6251     * Call this view's OnContextClickListener, if it is defined.
6252     *
6253     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6254     *         otherwise.
6255     */
6256    public boolean performContextClick() {
6257        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6258
6259        boolean handled = false;
6260        ListenerInfo li = mListenerInfo;
6261        if (li != null && li.mOnContextClickListener != null) {
6262            handled = li.mOnContextClickListener.onContextClick(View.this);
6263        }
6264        if (handled) {
6265            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6266        }
6267        return handled;
6268    }
6269
6270    /**
6271     * Performs button-related actions during a touch down event.
6272     *
6273     * @param event The event.
6274     * @return True if the down was consumed.
6275     *
6276     * @hide
6277     */
6278    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6279        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6280            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6281            showContextMenu(event.getX(), event.getY());
6282            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6283            return true;
6284        }
6285        return false;
6286    }
6287
6288    /**
6289     * Shows the context menu for this view.
6290     *
6291     * @return {@code true} if the context menu was shown, {@code false}
6292     *         otherwise
6293     * @see #showContextMenu(float, float)
6294     */
6295    public boolean showContextMenu() {
6296        return getParent().showContextMenuForChild(this);
6297    }
6298
6299    /**
6300     * Shows the context menu for this view anchored to the specified
6301     * view-relative coordinate.
6302     *
6303     * @param x the X coordinate in pixels relative to the view to which the
6304     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6305     * @param y the Y coordinate in pixels relative to the view to which the
6306     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6307     * @return {@code true} if the context menu was shown, {@code false}
6308     *         otherwise
6309     */
6310    public boolean showContextMenu(float x, float y) {
6311        return getParent().showContextMenuForChild(this, x, y);
6312    }
6313
6314    /**
6315     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6316     *
6317     * @param callback Callback that will control the lifecycle of the action mode
6318     * @return The new action mode if it is started, null otherwise
6319     *
6320     * @see ActionMode
6321     * @see #startActionMode(android.view.ActionMode.Callback, int)
6322     */
6323    public ActionMode startActionMode(ActionMode.Callback callback) {
6324        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6325    }
6326
6327    /**
6328     * Start an action mode with the given type.
6329     *
6330     * @param callback Callback that will control the lifecycle of the action mode
6331     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6332     * @return The new action mode if it is started, null otherwise
6333     *
6334     * @see ActionMode
6335     */
6336    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6337        ViewParent parent = getParent();
6338        if (parent == null) return null;
6339        try {
6340            return parent.startActionModeForChild(this, callback, type);
6341        } catch (AbstractMethodError ame) {
6342            // Older implementations of custom views might not implement this.
6343            return parent.startActionModeForChild(this, callback);
6344        }
6345    }
6346
6347    /**
6348     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6349     * Context, creating a unique View identifier to retrieve the result.
6350     *
6351     * @param intent The Intent to be started.
6352     * @param requestCode The request code to use.
6353     * @hide
6354     */
6355    public void startActivityForResult(Intent intent, int requestCode) {
6356        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6357        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6358    }
6359
6360    /**
6361     * If this View corresponds to the calling who, dispatches the activity result.
6362     * @param who The identifier for the targeted View to receive the result.
6363     * @param requestCode The integer request code originally supplied to
6364     *                    startActivityForResult(), allowing you to identify who this
6365     *                    result came from.
6366     * @param resultCode The integer result code returned by the child activity
6367     *                   through its setResult().
6368     * @param data An Intent, which can return result data to the caller
6369     *               (various data can be attached to Intent "extras").
6370     * @return {@code true} if the activity result was dispatched.
6371     * @hide
6372     */
6373    public boolean dispatchActivityResult(
6374            String who, int requestCode, int resultCode, Intent data) {
6375        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6376            onActivityResult(requestCode, resultCode, data);
6377            mStartActivityRequestWho = null;
6378            return true;
6379        }
6380        return false;
6381    }
6382
6383    /**
6384     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6385     *
6386     * @param requestCode The integer request code originally supplied to
6387     *                    startActivityForResult(), allowing you to identify who this
6388     *                    result came from.
6389     * @param resultCode The integer result code returned by the child activity
6390     *                   through its setResult().
6391     * @param data An Intent, which can return result data to the caller
6392     *               (various data can be attached to Intent "extras").
6393     * @hide
6394     */
6395    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6396        // Do nothing.
6397    }
6398
6399    /**
6400     * Register a callback to be invoked when a hardware key is pressed in this view.
6401     * Key presses in software input methods will generally not trigger the methods of
6402     * this listener.
6403     * @param l the key listener to attach to this view
6404     */
6405    public void setOnKeyListener(OnKeyListener l) {
6406        getListenerInfo().mOnKeyListener = l;
6407    }
6408
6409    /**
6410     * Register a callback to be invoked when a touch event is sent to this view.
6411     * @param l the touch listener to attach to this view
6412     */
6413    public void setOnTouchListener(OnTouchListener l) {
6414        getListenerInfo().mOnTouchListener = l;
6415    }
6416
6417    /**
6418     * Register a callback to be invoked when a generic motion event is sent to this view.
6419     * @param l the generic motion listener to attach to this view
6420     */
6421    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6422        getListenerInfo().mOnGenericMotionListener = l;
6423    }
6424
6425    /**
6426     * Register a callback to be invoked when a hover event is sent to this view.
6427     * @param l the hover listener to attach to this view
6428     */
6429    public void setOnHoverListener(OnHoverListener l) {
6430        getListenerInfo().mOnHoverListener = l;
6431    }
6432
6433    /**
6434     * Register a drag event listener callback object for this View. The parameter is
6435     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6436     * View, the system calls the
6437     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6438     * @param l An implementation of {@link android.view.View.OnDragListener}.
6439     */
6440    public void setOnDragListener(OnDragListener l) {
6441        getListenerInfo().mOnDragListener = l;
6442    }
6443
6444    /**
6445     * Give this view focus. This will cause
6446     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6447     *
6448     * Note: this does not check whether this {@link View} should get focus, it just
6449     * gives it focus no matter what.  It should only be called internally by framework
6450     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6451     *
6452     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6453     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6454     *        focus moved when requestFocus() is called. It may not always
6455     *        apply, in which case use the default View.FOCUS_DOWN.
6456     * @param previouslyFocusedRect The rectangle of the view that had focus
6457     *        prior in this View's coordinate system.
6458     */
6459    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6460        if (DBG) {
6461            System.out.println(this + " requestFocus()");
6462        }
6463
6464        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6465            mPrivateFlags |= PFLAG_FOCUSED;
6466
6467            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6468
6469            if (mParent != null) {
6470                mParent.requestChildFocus(this, this);
6471                setFocusedInCluster();
6472            }
6473
6474            if (mAttachInfo != null) {
6475                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6476            }
6477
6478            onFocusChanged(true, direction, previouslyFocusedRect);
6479            refreshDrawableState();
6480        }
6481    }
6482
6483    /**
6484     * Sets this view's preference for reveal behavior when it gains focus.
6485     *
6486     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6487     * this view would prefer to be brought fully into view when it gains focus.
6488     * For example, a text field that a user is meant to type into. Other views such
6489     * as scrolling containers may prefer to opt-out of this behavior.</p>
6490     *
6491     * <p>The default value for views is true, though subclasses may change this
6492     * based on their preferred behavior.</p>
6493     *
6494     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6495     *
6496     * @see #getRevealOnFocusHint()
6497     */
6498    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6499        if (revealOnFocus) {
6500            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6501        } else {
6502            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6503        }
6504    }
6505
6506    /**
6507     * Returns this view's preference for reveal behavior when it gains focus.
6508     *
6509     * <p>When this method returns true for a child view requesting focus, ancestor
6510     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6511     * should make a best effort to make the newly focused child fully visible to the user.
6512     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6513     * other properties affecting visibility to the user as part of the focus change.</p>
6514     *
6515     * @return true if this view would prefer to become fully visible when it gains focus,
6516     *         false if it would prefer not to disrupt scroll positioning
6517     *
6518     * @see #setRevealOnFocusHint(boolean)
6519     */
6520    public final boolean getRevealOnFocusHint() {
6521        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6522    }
6523
6524    /**
6525     * Populates <code>outRect</code> with the hotspot bounds. By default,
6526     * the hotspot bounds are identical to the screen bounds.
6527     *
6528     * @param outRect rect to populate with hotspot bounds
6529     * @hide Only for internal use by views and widgets.
6530     */
6531    public void getHotspotBounds(Rect outRect) {
6532        final Drawable background = getBackground();
6533        if (background != null) {
6534            background.getHotspotBounds(outRect);
6535        } else {
6536            getBoundsOnScreen(outRect);
6537        }
6538    }
6539
6540    /**
6541     * Request that a rectangle of this view be visible on the screen,
6542     * scrolling if necessary just enough.
6543     *
6544     * <p>A View should call this if it maintains some notion of which part
6545     * of its content is interesting.  For example, a text editing view
6546     * should call this when its cursor moves.
6547     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6548     * It should not be affected by which part of the View is currently visible or its scroll
6549     * position.
6550     *
6551     * @param rectangle The rectangle in the View's content coordinate space
6552     * @return Whether any parent scrolled.
6553     */
6554    public boolean requestRectangleOnScreen(Rect rectangle) {
6555        return requestRectangleOnScreen(rectangle, false);
6556    }
6557
6558    /**
6559     * Request that a rectangle of this view be visible on the screen,
6560     * scrolling if necessary just enough.
6561     *
6562     * <p>A View should call this if it maintains some notion of which part
6563     * of its content is interesting.  For example, a text editing view
6564     * should call this when its cursor moves.
6565     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6566     * It should not be affected by which part of the View is currently visible or its scroll
6567     * position.
6568     * <p>When <code>immediate</code> is set to true, scrolling will not be
6569     * animated.
6570     *
6571     * @param rectangle The rectangle in the View's content coordinate space
6572     * @param immediate True to forbid animated scrolling, false otherwise
6573     * @return Whether any parent scrolled.
6574     */
6575    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6576        if (mParent == null) {
6577            return false;
6578        }
6579
6580        View child = this;
6581
6582        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6583        position.set(rectangle);
6584
6585        ViewParent parent = mParent;
6586        boolean scrolled = false;
6587        while (parent != null) {
6588            rectangle.set((int) position.left, (int) position.top,
6589                    (int) position.right, (int) position.bottom);
6590
6591            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6592
6593            if (!(parent instanceof View)) {
6594                break;
6595            }
6596
6597            // move it from child's content coordinate space to parent's content coordinate space
6598            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6599
6600            child = (View) parent;
6601            parent = child.getParent();
6602        }
6603
6604        return scrolled;
6605    }
6606
6607    /**
6608     * Called when this view wants to give up focus. If focus is cleared
6609     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6610     * <p>
6611     * <strong>Note:</strong> When a View clears focus the framework is trying
6612     * to give focus to the first focusable View from the top. Hence, if this
6613     * View is the first from the top that can take focus, then all callbacks
6614     * related to clearing focus will be invoked after which the framework will
6615     * give focus to this view.
6616     * </p>
6617     */
6618    public void clearFocus() {
6619        if (DBG) {
6620            System.out.println(this + " clearFocus()");
6621        }
6622
6623        clearFocusInternal(null, true, true);
6624    }
6625
6626    /**
6627     * Clears focus from the view, optionally propagating the change up through
6628     * the parent hierarchy and requesting that the root view place new focus.
6629     *
6630     * @param propagate whether to propagate the change up through the parent
6631     *            hierarchy
6632     * @param refocus when propagate is true, specifies whether to request the
6633     *            root view place new focus
6634     */
6635    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6636        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6637            mPrivateFlags &= ~PFLAG_FOCUSED;
6638
6639            if (propagate && mParent != null) {
6640                mParent.clearChildFocus(this);
6641            }
6642
6643            onFocusChanged(false, 0, null);
6644            refreshDrawableState();
6645
6646            if (propagate && (!refocus || !rootViewRequestFocus())) {
6647                notifyGlobalFocusCleared(this);
6648            }
6649        }
6650    }
6651
6652    void notifyGlobalFocusCleared(View oldFocus) {
6653        if (oldFocus != null && mAttachInfo != null) {
6654            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6655        }
6656    }
6657
6658    boolean rootViewRequestFocus() {
6659        final View root = getRootView();
6660        return root != null && root.requestFocus();
6661    }
6662
6663    /**
6664     * Called internally by the view system when a new view is getting focus.
6665     * This is what clears the old focus.
6666     * <p>
6667     * <b>NOTE:</b> The parent view's focused child must be updated manually
6668     * after calling this method. Otherwise, the view hierarchy may be left in
6669     * an inconstent state.
6670     */
6671    void unFocus(View focused) {
6672        if (DBG) {
6673            System.out.println(this + " unFocus()");
6674        }
6675
6676        clearFocusInternal(focused, false, false);
6677    }
6678
6679    /**
6680     * Returns true if this view has focus itself, or is the ancestor of the
6681     * view that has focus.
6682     *
6683     * @return True if this view has or contains focus, false otherwise.
6684     */
6685    @ViewDebug.ExportedProperty(category = "focus")
6686    public boolean hasFocus() {
6687        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6688    }
6689
6690    /**
6691     * Returns true if this view is focusable or if it contains a reachable View
6692     * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6693     * is a view whose parents do not block descendants focus.
6694     * Only {@link #VISIBLE} views are considered focusable.
6695     *
6696     * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6697     * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6698     * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6699     * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6700     * {@code false} for views not explicitly marked as focusable.
6701     * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6702     * behavior.</p>
6703     *
6704     * @return {@code true} if the view is focusable or if the view contains a focusable
6705     *         view, {@code false} otherwise
6706     *
6707     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6708     * @see ViewGroup#getTouchscreenBlocksFocus()
6709     * @see #hasExplicitFocusable()
6710     */
6711    public boolean hasFocusable() {
6712        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6713    }
6714
6715    /**
6716     * Returns true if this view is focusable or if it contains a reachable View
6717     * for which {@link #hasExplicitFocusable()} returns {@code true}.
6718     * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6719     * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6720     * {@link #FOCUSABLE} are considered focusable.
6721     *
6722     * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6723     * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6724     * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6725     * to focusable will not.</p>
6726     *
6727     * @return {@code true} if the view is focusable or if the view contains a focusable
6728     *         view, {@code false} otherwise
6729     *
6730     * @see #hasFocusable()
6731     */
6732    public boolean hasExplicitFocusable() {
6733        return hasFocusable(false, true);
6734    }
6735
6736    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6737        if (!isFocusableInTouchMode()) {
6738            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6739                final ViewGroup g = (ViewGroup) p;
6740                if (g.shouldBlockFocusForTouchscreen()) {
6741                    return false;
6742                }
6743            }
6744        }
6745
6746        // Invisible and gone views are never focusable.
6747        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6748            return false;
6749        }
6750
6751        // Only use effective focusable value when allowed.
6752        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6753            return true;
6754        }
6755
6756        return false;
6757    }
6758
6759    /**
6760     * Called by the view system when the focus state of this view changes.
6761     * When the focus change event is caused by directional navigation, direction
6762     * and previouslyFocusedRect provide insight into where the focus is coming from.
6763     * When overriding, be sure to call up through to the super class so that
6764     * the standard focus handling will occur.
6765     *
6766     * @param gainFocus True if the View has focus; false otherwise.
6767     * @param direction The direction focus has moved when requestFocus()
6768     *                  is called to give this view focus. Values are
6769     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6770     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6771     *                  It may not always apply, in which case use the default.
6772     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6773     *        system, of the previously focused view.  If applicable, this will be
6774     *        passed in as finer grained information about where the focus is coming
6775     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6776     */
6777    @CallSuper
6778    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6779            @Nullable Rect previouslyFocusedRect) {
6780        if (gainFocus) {
6781            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6782        } else {
6783            notifyViewAccessibilityStateChangedIfNeeded(
6784                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6785        }
6786
6787        // Here we check whether we still need the default focus highlight, and switch it on/off.
6788        switchDefaultFocusHighlight();
6789
6790        InputMethodManager imm = InputMethodManager.peekInstance();
6791        if (!gainFocus) {
6792            if (isPressed()) {
6793                setPressed(false);
6794            }
6795            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6796                imm.focusOut(this);
6797            }
6798            onFocusLost();
6799        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6800            imm.focusIn(this);
6801        }
6802
6803        invalidate(true);
6804        ListenerInfo li = mListenerInfo;
6805        if (li != null && li.mOnFocusChangeListener != null) {
6806            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6807        }
6808
6809        if (mAttachInfo != null) {
6810            mAttachInfo.mKeyDispatchState.reset(this);
6811        }
6812
6813        notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6814    }
6815
6816    private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6817        if (isAutofillable() && isAttachedToWindow()) {
6818            AutofillManager afm = getAutofillManager();
6819            if (afm != null) {
6820                if (enter && hasWindowFocus() && isFocused()) {
6821                    afm.notifyViewEntered(this);
6822                } else if (!hasWindowFocus() || !isFocused()) {
6823                    afm.notifyViewExited(this);
6824                }
6825            }
6826        }
6827    }
6828
6829    /**
6830     * Sends an accessibility event of the given type. If accessibility is
6831     * not enabled this method has no effect. The default implementation calls
6832     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6833     * to populate information about the event source (this View), then calls
6834     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6835     * populate the text content of the event source including its descendants,
6836     * and last calls
6837     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6838     * on its parent to request sending of the event to interested parties.
6839     * <p>
6840     * If an {@link AccessibilityDelegate} has been specified via calling
6841     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6842     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6843     * responsible for handling this call.
6844     * </p>
6845     *
6846     * @param eventType The type of the event to send, as defined by several types from
6847     * {@link android.view.accessibility.AccessibilityEvent}, such as
6848     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6849     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6850     *
6851     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6852     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6853     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6854     * @see AccessibilityDelegate
6855     */
6856    public void sendAccessibilityEvent(int eventType) {
6857        if (mAccessibilityDelegate != null) {
6858            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6859        } else {
6860            sendAccessibilityEventInternal(eventType);
6861        }
6862    }
6863
6864    /**
6865     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6866     * {@link AccessibilityEvent} to make an announcement which is related to some
6867     * sort of a context change for which none of the events representing UI transitions
6868     * is a good fit. For example, announcing a new page in a book. If accessibility
6869     * is not enabled this method does nothing.
6870     *
6871     * @param text The announcement text.
6872     */
6873    public void announceForAccessibility(CharSequence text) {
6874        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6875            AccessibilityEvent event = AccessibilityEvent.obtain(
6876                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6877            onInitializeAccessibilityEvent(event);
6878            event.getText().add(text);
6879            event.setContentDescription(null);
6880            mParent.requestSendAccessibilityEvent(this, event);
6881        }
6882    }
6883
6884    /**
6885     * @see #sendAccessibilityEvent(int)
6886     *
6887     * Note: Called from the default {@link AccessibilityDelegate}.
6888     *
6889     * @hide
6890     */
6891    public void sendAccessibilityEventInternal(int eventType) {
6892        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6893            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
6894        }
6895    }
6896
6897    /**
6898     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
6899     * takes as an argument an empty {@link AccessibilityEvent} and does not
6900     * perform a check whether accessibility is enabled.
6901     * <p>
6902     * If an {@link AccessibilityDelegate} has been specified via calling
6903     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6904     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
6905     * is responsible for handling this call.
6906     * </p>
6907     *
6908     * @param event The event to send.
6909     *
6910     * @see #sendAccessibilityEvent(int)
6911     */
6912    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
6913        if (mAccessibilityDelegate != null) {
6914            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6915        } else {
6916            sendAccessibilityEventUncheckedInternal(event);
6917        }
6918    }
6919
6920    /**
6921     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6922     *
6923     * Note: Called from the default {@link AccessibilityDelegate}.
6924     *
6925     * @hide
6926     */
6927    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6928        if (!isShown()) {
6929            return;
6930        }
6931        onInitializeAccessibilityEvent(event);
6932        // Only a subset of accessibility events populates text content.
6933        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6934            dispatchPopulateAccessibilityEvent(event);
6935        }
6936        // In the beginning we called #isShown(), so we know that getParent() is not null.
6937        ViewParent parent = getParent();
6938        if (parent != null) {
6939            getParent().requestSendAccessibilityEvent(this, event);
6940        }
6941    }
6942
6943    /**
6944     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6945     * to its children for adding their text content to the event. Note that the
6946     * event text is populated in a separate dispatch path since we add to the
6947     * event not only the text of the source but also the text of all its descendants.
6948     * A typical implementation will call
6949     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6950     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6951     * on each child. Override this method if custom population of the event text
6952     * content is required.
6953     * <p>
6954     * If an {@link AccessibilityDelegate} has been specified via calling
6955     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6956     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6957     * is responsible for handling this call.
6958     * </p>
6959     * <p>
6960     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6961     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6962     * </p>
6963     *
6964     * @param event The event.
6965     *
6966     * @return True if the event population was completed.
6967     */
6968    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6969        if (mAccessibilityDelegate != null) {
6970            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6971        } else {
6972            return dispatchPopulateAccessibilityEventInternal(event);
6973        }
6974    }
6975
6976    /**
6977     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6978     *
6979     * Note: Called from the default {@link AccessibilityDelegate}.
6980     *
6981     * @hide
6982     */
6983    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6984        onPopulateAccessibilityEvent(event);
6985        return false;
6986    }
6987
6988    /**
6989     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6990     * giving a chance to this View to populate the accessibility event with its
6991     * text content. While this method is free to modify event
6992     * attributes other than text content, doing so should normally be performed in
6993     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6994     * <p>
6995     * Example: Adding formatted date string to an accessibility event in addition
6996     *          to the text added by the super implementation:
6997     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6998     *     super.onPopulateAccessibilityEvent(event);
6999     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
7000     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
7001     *         mCurrentDate.getTimeInMillis(), flags);
7002     *     event.getText().add(selectedDateUtterance);
7003     * }</pre>
7004     * <p>
7005     * If an {@link AccessibilityDelegate} has been specified via calling
7006     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7007     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7008     * is responsible for handling this call.
7009     * </p>
7010     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7011     * information to the event, in case the default implementation has basic information to add.
7012     * </p>
7013     *
7014     * @param event The accessibility event which to populate.
7015     *
7016     * @see #sendAccessibilityEvent(int)
7017     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7018     */
7019    @CallSuper
7020    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7021        if (mAccessibilityDelegate != null) {
7022            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7023        } else {
7024            onPopulateAccessibilityEventInternal(event);
7025        }
7026    }
7027
7028    /**
7029     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7030     *
7031     * Note: Called from the default {@link AccessibilityDelegate}.
7032     *
7033     * @hide
7034     */
7035    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7036    }
7037
7038    /**
7039     * Initializes an {@link AccessibilityEvent} with information about
7040     * this View which is the event source. In other words, the source of
7041     * an accessibility event is the view whose state change triggered firing
7042     * the event.
7043     * <p>
7044     * Example: Setting the password property of an event in addition
7045     *          to properties set by the super implementation:
7046     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7047     *     super.onInitializeAccessibilityEvent(event);
7048     *     event.setPassword(true);
7049     * }</pre>
7050     * <p>
7051     * If an {@link AccessibilityDelegate} has been specified via calling
7052     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7053     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7054     * is responsible for handling this call.
7055     * </p>
7056     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7057     * information to the event, in case the default implementation has basic information to add.
7058     * </p>
7059     * @param event The event to initialize.
7060     *
7061     * @see #sendAccessibilityEvent(int)
7062     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7063     */
7064    @CallSuper
7065    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7066        if (mAccessibilityDelegate != null) {
7067            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7068        } else {
7069            onInitializeAccessibilityEventInternal(event);
7070        }
7071    }
7072
7073    /**
7074     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7075     *
7076     * Note: Called from the default {@link AccessibilityDelegate}.
7077     *
7078     * @hide
7079     */
7080    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7081        event.setSource(this);
7082        event.setClassName(getAccessibilityClassName());
7083        event.setPackageName(getContext().getPackageName());
7084        event.setEnabled(isEnabled());
7085        event.setContentDescription(mContentDescription);
7086
7087        switch (event.getEventType()) {
7088            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7089                ArrayList<View> focusablesTempList = (mAttachInfo != null)
7090                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7091                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7092                event.setItemCount(focusablesTempList.size());
7093                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7094                if (mAttachInfo != null) {
7095                    focusablesTempList.clear();
7096                }
7097            } break;
7098            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7099                CharSequence text = getIterableTextForAccessibility();
7100                if (text != null && text.length() > 0) {
7101                    event.setFromIndex(getAccessibilitySelectionStart());
7102                    event.setToIndex(getAccessibilitySelectionEnd());
7103                    event.setItemCount(text.length());
7104                }
7105            } break;
7106        }
7107    }
7108
7109    /**
7110     * Returns an {@link AccessibilityNodeInfo} representing this view from the
7111     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7112     * This method is responsible for obtaining an accessibility node info from a
7113     * pool of reusable instances and calling
7114     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7115     * initialize the former.
7116     * <p>
7117     * Note: The client is responsible for recycling the obtained instance by calling
7118     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7119     * </p>
7120     *
7121     * @return A populated {@link AccessibilityNodeInfo}.
7122     *
7123     * @see AccessibilityNodeInfo
7124     */
7125    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7126        if (mAccessibilityDelegate != null) {
7127            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7128        } else {
7129            return createAccessibilityNodeInfoInternal();
7130        }
7131    }
7132
7133    /**
7134     * @see #createAccessibilityNodeInfo()
7135     *
7136     * @hide
7137     */
7138    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7139        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7140        if (provider != null) {
7141            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7142        } else {
7143            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7144            onInitializeAccessibilityNodeInfo(info);
7145            return info;
7146        }
7147    }
7148
7149    /**
7150     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7151     * The base implementation sets:
7152     * <ul>
7153     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7154     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7155     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7156     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7157     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7158     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7159     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7160     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7161     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7162     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7163     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7164     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7165     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7166     * </ul>
7167     * <p>
7168     * Subclasses should override this method, call the super implementation,
7169     * and set additional attributes.
7170     * </p>
7171     * <p>
7172     * If an {@link AccessibilityDelegate} has been specified via calling
7173     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7174     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7175     * is responsible for handling this call.
7176     * </p>
7177     *
7178     * @param info The instance to initialize.
7179     */
7180    @CallSuper
7181    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7182        if (mAccessibilityDelegate != null) {
7183            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7184        } else {
7185            onInitializeAccessibilityNodeInfoInternal(info);
7186        }
7187    }
7188
7189    /**
7190     * Gets the location of this view in screen coordinates.
7191     *
7192     * @param outRect The output location
7193     * @hide
7194     */
7195    public void getBoundsOnScreen(Rect outRect) {
7196        getBoundsOnScreen(outRect, false);
7197    }
7198
7199    /**
7200     * Gets the location of this view in screen coordinates.
7201     *
7202     * @param outRect The output location
7203     * @param clipToParent Whether to clip child bounds to the parent ones.
7204     * @hide
7205     */
7206    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7207        if (mAttachInfo == null) {
7208            return;
7209        }
7210
7211        RectF position = mAttachInfo.mTmpTransformRect;
7212        position.set(0, 0, mRight - mLeft, mBottom - mTop);
7213
7214        if (!hasIdentityMatrix()) {
7215            getMatrix().mapRect(position);
7216        }
7217
7218        position.offset(mLeft, mTop);
7219
7220        ViewParent parent = mParent;
7221        while (parent instanceof View) {
7222            View parentView = (View) parent;
7223
7224            position.offset(-parentView.mScrollX, -parentView.mScrollY);
7225
7226            if (clipToParent) {
7227                position.left = Math.max(position.left, 0);
7228                position.top = Math.max(position.top, 0);
7229                position.right = Math.min(position.right, parentView.getWidth());
7230                position.bottom = Math.min(position.bottom, parentView.getHeight());
7231            }
7232
7233            if (!parentView.hasIdentityMatrix()) {
7234                parentView.getMatrix().mapRect(position);
7235            }
7236
7237            position.offset(parentView.mLeft, parentView.mTop);
7238
7239            parent = parentView.mParent;
7240        }
7241
7242        if (parent instanceof ViewRootImpl) {
7243            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7244            position.offset(0, -viewRootImpl.mCurScrollY);
7245        }
7246
7247        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7248
7249        outRect.set(Math.round(position.left), Math.round(position.top),
7250                Math.round(position.right), Math.round(position.bottom));
7251    }
7252
7253    /**
7254     * Return the class name of this object to be used for accessibility purposes.
7255     * Subclasses should only override this if they are implementing something that
7256     * should be seen as a completely new class of view when used by accessibility,
7257     * unrelated to the class it is deriving from.  This is used to fill in
7258     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7259     */
7260    public CharSequence getAccessibilityClassName() {
7261        return View.class.getName();
7262    }
7263
7264    /**
7265     * Called when assist structure is being retrieved from a view as part of
7266     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7267     * @param structure Fill in with structured view data.  The default implementation
7268     * fills in all data that can be inferred from the view itself.
7269     */
7270    public void onProvideStructure(ViewStructure structure) {
7271        onProvideStructureForAssistOrAutofill(structure, false);
7272    }
7273
7274    /**
7275     * Called when assist structure is being retrieved from a view as part of an autofill request.
7276     *
7277     * <p>This method already provides most of what's needed for autofill, but should be overridden
7278     * when:
7279     * <ol>
7280     * <li>The view contents does not include PII (Personally Identifiable Information), so it
7281     * can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7282     * <li>It must set fields such {@link ViewStructure#setText(CharSequence)},
7283     * {@link ViewStructure#setAutofillOptions(String[])}, or {@link ViewStructure#setUrl(String)}.
7284     * </ol>
7285     *
7286     * @param structure Fill in with structured view data. The default implementation
7287     * fills in all data that can be inferred from the view itself.
7288     * @param flags optional flags (currently {@code 0}).
7289     */
7290    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
7291        onProvideStructureForAssistOrAutofill(structure, true);
7292    }
7293
7294    private void setAutofillId(ViewStructure structure) {
7295        // The autofill id needs to be unique, but its value doesn't matter,
7296        // so it's better to reuse the accessibility id to save space.
7297        structure.setAutofillId(getAccessibilityViewId());
7298    }
7299
7300    private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7301            boolean forAutofill) {
7302        final int id = mID;
7303        if (id != NO_ID && !isViewIdGenerated(id)) {
7304            String pkg, type, entry;
7305            try {
7306                final Resources res = getResources();
7307                entry = res.getResourceEntryName(id);
7308                type = res.getResourceTypeName(id);
7309                pkg = res.getResourcePackageName(id);
7310            } catch (Resources.NotFoundException e) {
7311                entry = type = pkg = null;
7312            }
7313            structure.setId(id, pkg, type, entry);
7314        } else {
7315            structure.setId(id, null, null, null);
7316        }
7317
7318        if (forAutofill) {
7319            setAutofillId(structure);
7320            final @AutofillType int autofillType = getAutofillType();
7321            // Don't need to fill autofill info if view does not support it.
7322            // For example, only TextViews that are editable support autofill
7323            if (autofillType != AUTOFILL_TYPE_NONE) {
7324                structure.setAutofillType(autofillType);
7325                structure.setAutofillHints(getAutofillHints());
7326                structure.setAutofillValue(getAutofillValue());
7327            }
7328        }
7329
7330        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
7331        if (!hasIdentityMatrix()) {
7332            structure.setTransformation(getMatrix());
7333        }
7334        structure.setElevation(getZ());
7335        structure.setVisibility(getVisibility());
7336        structure.setEnabled(isEnabled());
7337        if (isClickable()) {
7338            structure.setClickable(true);
7339        }
7340        if (isFocusable()) {
7341            structure.setFocusable(true);
7342        }
7343        if (isFocused()) {
7344            structure.setFocused(true);
7345        }
7346        if (isAccessibilityFocused()) {
7347            structure.setAccessibilityFocused(true);
7348        }
7349        if (isSelected()) {
7350            structure.setSelected(true);
7351        }
7352        if (isActivated()) {
7353            structure.setActivated(true);
7354        }
7355        if (isLongClickable()) {
7356            structure.setLongClickable(true);
7357        }
7358        if (this instanceof Checkable) {
7359            structure.setCheckable(true);
7360            if (((Checkable)this).isChecked()) {
7361                structure.setChecked(true);
7362            }
7363        }
7364        if (isOpaque()) {
7365            structure.setOpaque(true);
7366        }
7367        if (isContextClickable()) {
7368            structure.setContextClickable(true);
7369        }
7370        structure.setClassName(getAccessibilityClassName().toString());
7371        structure.setContentDescription(getContentDescription());
7372    }
7373
7374    /**
7375     * Called when assist structure is being retrieved from a view as part of
7376     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7377     * generate additional virtual structure under this view.  The defaullt implementation
7378     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7379     * view's virtual accessibility nodes, if any.  You can override this for a more
7380     * optimal implementation providing this data.
7381     */
7382    public void onProvideVirtualStructure(ViewStructure structure) {
7383        onProvideVirtualStructureForAssistOrAutofill(structure, false);
7384    }
7385
7386    /**
7387     * Called when assist structure is being retrieved from a view as part of an autofill request
7388     * to generate additional virtual structure under this view.
7389     *
7390     * <p>The default implementation uses {@link #getAccessibilityNodeProvider()} to try to
7391     * generate this from the view's virtual accessibility nodes, if any. You can override this
7392     * for a more optimal implementation providing this data.
7393     *
7394     * <p>When implementing this method, subclasses must follow the rules below:
7395     *
7396     * <ol>
7397     * <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7398     * children.
7399     * <li>Call
7400     * {@link android.view.autofill.AutofillManager#notifyViewEntered} and
7401     * {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7402     * when the focus inside the view changed.
7403     * <li>Call {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int,
7404     * AutofillValue)} when the value of a child changed.
7405     * <li>Call {@link AutofillManager#commit()} when the autofill context
7406     * of the view structure changed and you want the current autofill interaction if such
7407     * to be commited.
7408     * <li>Call {@link AutofillManager#cancel()} ()} when the autofill context
7409     * of the view structure changed and you want the current autofill interaction if such
7410     * to be cancelled.
7411     * </ol>
7412     *
7413     * @param structure Fill in with structured view data.
7414     * @param flags optional flags (currently {@code 0}).
7415     */
7416    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7417        onProvideVirtualStructureForAssistOrAutofill(structure, true);
7418    }
7419
7420    private void onProvideVirtualStructureForAssistOrAutofill(ViewStructure structure,
7421            boolean forAutofill) {
7422        if (forAutofill) {
7423            setAutofillId(structure);
7424        }
7425        // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
7426        // this method should take a boolean with the type of request.
7427        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7428        if (provider != null) {
7429            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7430            structure.setChildCount(1);
7431            ViewStructure root = structure.newChild(0);
7432            if (forAutofill) {
7433                setAutofillId(root);
7434            }
7435            populateVirtualStructure(root, provider, info, forAutofill);
7436            info.recycle();
7437        }
7438    }
7439
7440    /**
7441     * Automatically fills the content of this view with the {@code value}.
7442     *
7443     * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
7444     * {@link #getAutofillValue()}, and {@link #onProvideAutofillStructure(ViewStructure, int)}
7445     * to support the Autofill Framework.
7446     *
7447     * <p>Typically, it is implemented by:
7448     *
7449     * <ol>
7450     * <li>Calling the proper getter method on {@link AutofillValue} to fetch the actual value.
7451     * <li>Passing the actual value to the equivalent setter in the view.
7452     * </ol>
7453     *
7454     * <p>For example, a text-field view would call:
7455     * <pre class="prettyprint">
7456     * CharSequence text = value.getTextValue();
7457     * if (text != null) {
7458     *     setText(text);
7459     * }
7460     * </pre>
7461     *
7462     * <p>If the value is updated asyncronously the next call to
7463     * {@link AutofillManager#notifyValueChanged(View)} must happen <u>after</u> the value was
7464     * changed to the autofilled value. If not, the view will not be considered autofilled.
7465     *
7466     * @param value value to be autofilled.
7467     */
7468    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7469    }
7470
7471    /**
7472     * Automatically fills the content of a virtual views.
7473     *
7474     * <p>See {@link #autofill(AutofillValue)} and
7475     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info.
7476     * <p>To indicate that a virtual view was autofilled
7477     * <code>@android:drawable/autofilled_highlight</code> should be drawn over it until the data
7478     * changes.
7479     *
7480     * @param values map of values to be autofilled, keyed by virtual child id.
7481     */
7482    public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
7483    }
7484
7485    /**
7486     * Describes the autofill type that should be used on calls to
7487     * {@link #autofill(AutofillValue)} and {@link #autofill(SparseArray)}.
7488     *
7489     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
7490     * {@link #autofill(AutofillValue)} to support the Autofill Framework.
7491     */
7492    public @AutofillType int getAutofillType() {
7493        return AUTOFILL_TYPE_NONE;
7494    }
7495
7496    /**
7497     * Describes the content of a view so that a autofill service can fill in the appropriate data.
7498     *
7499     * @return The hints set via the attribute or {@code null} if no hint it set.
7500     *
7501     * @attr ref android.R.styleable#View_autofillHints
7502     */
7503    @ViewDebug.ExportedProperty()
7504    @Nullable public String[] getAutofillHints() {
7505        return mAutofillHints;
7506    }
7507
7508    /**
7509     * @hide
7510     */
7511    public boolean isAutofilled() {
7512        return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
7513    }
7514
7515    /**
7516     * Gets the {@link View}'s current autofill value.
7517     *
7518     * <p>By default returns {@code null}, but views should override it (and
7519     * {@link #autofill(AutofillValue)}, and {@link #getAutofillType()} to support the Autofill
7520     * Framework.
7521     */
7522    @Nullable
7523    public AutofillValue getAutofillValue() {
7524        return null;
7525    }
7526
7527    /**
7528     * Gets the mode for determining whether this View is important for autofill.
7529     *
7530     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7531     *
7532     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7533     * {@link #setImportantForAutofill(int)}.
7534     *
7535     * @attr ref android.R.styleable#View_importantForAutofill
7536     */
7537    @ViewDebug.ExportedProperty(mapping = {
7538            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7539            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7540            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no")})
7541    public @AutofillImportance int getImportantForAutofill() {
7542        return (mPrivateFlags3
7543                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7544    }
7545
7546    /**
7547     * Sets the mode for determining whether this View is important for autofill.
7548     *
7549     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
7550     *
7551     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7552     * or {@link #IMPORTANT_FOR_AUTOFILL_NO}.
7553     *
7554     * @attr ref android.R.styleable#View_importantForAutofill
7555     */
7556    public void setImportantForAutofill(@AutofillImportance int mode) {
7557        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7558        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7559                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7560    }
7561
7562    /**
7563     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7564     * associated with this View should be included in a {@link ViewStructure} used for
7565     * autofill purposes.
7566     *
7567     * <p>Generally speaking, a view is important for autofill if:
7568     * <ol>
7569     * <li>The view can-be autofilled by an {@link android.service.autofill.AutofillService}.
7570     * <li>The view contents can help an {@link android.service.autofill.AutofillService} to
7571     * autofill other views.
7572     * <ol>
7573     *
7574     * <p>For example, view containers should typically return {@code false} for performance reasons
7575     * (since the important info is provided by their children), but if the container is actually
7576     * whose children are part of a compound view, it should return {@code true} (and then override
7577     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7578     * {@link #onProvideAutofillStructure(ViewStructure, int)} so its children are not included in
7579     * the structure). On the other hand, views representing labels or editable fields should
7580     * typically return {@code true}, but in some cases they could return {@code false} (for
7581     * example, if they're part of a "Captcha" mechanism).
7582     *
7583     * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
7584     * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
7585     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
7586     * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
7587     * should use {@link #setImportantForAutofill(int)} instead.
7588     *
7589     * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
7590     * excluded from the structure; for example, if the user explicitly requested autofill, the
7591     * View might be always included.
7592     *
7593     * <p>This decision applies just for the view, not its children - if the view children are not
7594     * important for autofill, the view should override
7595     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
7596     * {@link #onProvideAutofillStructure(ViewStructure, int)} (instead of calling
7597     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} for each child).
7598     *
7599     * @return whether the view is considered important for autofill.
7600     *
7601     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7602     * @see #IMPORTANT_FOR_AUTOFILL_YES
7603     * @see #IMPORTANT_FOR_AUTOFILL_NO
7604     */
7605    public final boolean isImportantForAutofill() {
7606        final int flag = getImportantForAutofill();
7607
7608        // First, check if view explicity set it to YES or NO
7609        if ((flag & IMPORTANT_FOR_AUTOFILL_YES) != 0) {
7610            return true;
7611        }
7612        if ((flag & IMPORTANT_FOR_AUTOFILL_NO) != 0) {
7613            return false;
7614        }
7615
7616        // Then use some heuristics to handle AUTO.
7617
7618        // Always include views that have a explicity resource id.
7619        final int id = mID;
7620        if (id != NO_ID && !isViewIdGenerated(id)) {
7621            final Resources res = getResources();
7622            String entry = null;
7623            String pkg = null;
7624            try {
7625                entry = res.getResourceEntryName(id);
7626                pkg = res.getResourcePackageName(id);
7627            } catch (Resources.NotFoundException e) {
7628                // ignore
7629            }
7630            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
7631                return true;
7632            }
7633        }
7634
7635        // Otherwise, assume it's not important...
7636        return false;
7637    }
7638
7639    @Nullable
7640    private AutofillManager getAutofillManager() {
7641        return mContext.getSystemService(AutofillManager.class);
7642    }
7643
7644    private boolean isAutofillable() {
7645        return getAutofillType() != AUTOFILL_TYPE_NONE && !isAutofillBlocked();
7646    }
7647
7648    private void populateVirtualStructure(ViewStructure structure,
7649            AccessibilityNodeProvider provider, AccessibilityNodeInfo info, boolean forAutofill) {
7650        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7651                null, null, null);
7652        Rect rect = structure.getTempRect();
7653        info.getBoundsInParent(rect);
7654        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7655        structure.setVisibility(VISIBLE);
7656        structure.setEnabled(info.isEnabled());
7657        if (info.isClickable()) {
7658            structure.setClickable(true);
7659        }
7660        if (info.isFocusable()) {
7661            structure.setFocusable(true);
7662        }
7663        if (info.isFocused()) {
7664            structure.setFocused(true);
7665        }
7666        if (info.isAccessibilityFocused()) {
7667            structure.setAccessibilityFocused(true);
7668        }
7669        if (info.isSelected()) {
7670            structure.setSelected(true);
7671        }
7672        if (info.isLongClickable()) {
7673            structure.setLongClickable(true);
7674        }
7675        if (info.isCheckable()) {
7676            structure.setCheckable(true);
7677            if (info.isChecked()) {
7678                structure.setChecked(true);
7679            }
7680        }
7681        if (info.isContextClickable()) {
7682            structure.setContextClickable(true);
7683        }
7684        CharSequence cname = info.getClassName();
7685        structure.setClassName(cname != null ? cname.toString() : null);
7686        structure.setContentDescription(info.getContentDescription());
7687        if (!forAutofill && (info.getText() != null || info.getError() != null)) {
7688            // TODO(b/33197203) (b/33269702): when sanitized, try to use the Accessibility API to
7689            // just set sanitized values (like text coming from resource files), rather than not
7690            // setting it at all.
7691            structure.setText(info.getText(), info.getTextSelectionStart(),
7692                    info.getTextSelectionEnd());
7693        }
7694        final int NCHILDREN = info.getChildCount();
7695        if (NCHILDREN > 0) {
7696            structure.setChildCount(NCHILDREN);
7697            for (int i=0; i<NCHILDREN; i++) {
7698                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
7699                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
7700                ViewStructure child = structure.newChild(i);
7701                if (forAutofill) {
7702                    // TODO(b/33197203): add CTS test to autofill virtual children based on
7703                    // Accessibility API.
7704                    child.setAutofillId(structure, i);
7705                }
7706                populateVirtualStructure(child, provider, cinfo, forAutofill);
7707                cinfo.recycle();
7708            }
7709        }
7710    }
7711
7712    /**
7713     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
7714     * implementation calls {@link #onProvideStructure} and
7715     * {@link #onProvideVirtualStructure}.
7716     */
7717    public void dispatchProvideStructure(ViewStructure structure) {
7718        dispatchProvideStructureForAssistOrAutofill(structure, false);
7719    }
7720
7721    /**
7722     * Dispatch creation of {@link ViewStructure} down the hierarchy.
7723     *
7724     * <p>The structure must be filled according to the request type, which is set in the
7725     * {@code flags} parameter - see the documentation on each flag for more details.
7726     *
7727     * <p>The default implementation calls {@link #onProvideAutofillStructure(ViewStructure, int)}
7728     * and {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
7729     *
7730     * @param structure Fill in with structured view data.
7731     * @param flags optional flags (currently {@code 0}).
7732     */
7733    public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
7734        dispatchProvideStructureForAssistOrAutofill(structure, true);
7735    }
7736
7737    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
7738            boolean forAutofill) {
7739        boolean blocked = forAutofill ? isAutofillBlocked() : isAssistBlocked();
7740        if (!blocked) {
7741            if (forAutofill) {
7742                setAutofillId(structure);
7743                // NOTE: flags are not currently supported, hence 0
7744                onProvideAutofillStructure(structure, 0);
7745                onProvideAutofillVirtualStructure(structure, 0);
7746            } else {
7747                onProvideStructure(structure);
7748                onProvideVirtualStructure(structure);
7749            }
7750        } else {
7751            structure.setClassName(getAccessibilityClassName().toString());
7752            structure.setAssistBlocked(true);
7753        }
7754    }
7755
7756    /**
7757     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
7758     *
7759     * Note: Called from the default {@link AccessibilityDelegate}.
7760     *
7761     * @hide
7762     */
7763    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
7764        if (mAttachInfo == null) {
7765            return;
7766        }
7767
7768        Rect bounds = mAttachInfo.mTmpInvalRect;
7769
7770        getDrawingRect(bounds);
7771        info.setBoundsInParent(bounds);
7772
7773        getBoundsOnScreen(bounds, true);
7774        info.setBoundsInScreen(bounds);
7775
7776        ViewParent parent = getParentForAccessibility();
7777        if (parent instanceof View) {
7778            info.setParent((View) parent);
7779        }
7780
7781        if (mID != View.NO_ID) {
7782            View rootView = getRootView();
7783            if (rootView == null) {
7784                rootView = this;
7785            }
7786
7787            View label = rootView.findLabelForView(this, mID);
7788            if (label != null) {
7789                info.setLabeledBy(label);
7790            }
7791
7792            if ((mAttachInfo.mAccessibilityFetchFlags
7793                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
7794                    && Resources.resourceHasPackage(mID)) {
7795                try {
7796                    String viewId = getResources().getResourceName(mID);
7797                    info.setViewIdResourceName(viewId);
7798                } catch (Resources.NotFoundException nfe) {
7799                    /* ignore */
7800                }
7801            }
7802        }
7803
7804        if (mLabelForId != View.NO_ID) {
7805            View rootView = getRootView();
7806            if (rootView == null) {
7807                rootView = this;
7808            }
7809            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
7810            if (labeled != null) {
7811                info.setLabelFor(labeled);
7812            }
7813        }
7814
7815        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
7816            View rootView = getRootView();
7817            if (rootView == null) {
7818                rootView = this;
7819            }
7820            View next = rootView.findViewInsideOutShouldExist(this,
7821                    mAccessibilityTraversalBeforeId);
7822            if (next != null && next.includeForAccessibility()) {
7823                info.setTraversalBefore(next);
7824            }
7825        }
7826
7827        if (mAccessibilityTraversalAfterId != View.NO_ID) {
7828            View rootView = getRootView();
7829            if (rootView == null) {
7830                rootView = this;
7831            }
7832            View next = rootView.findViewInsideOutShouldExist(this,
7833                    mAccessibilityTraversalAfterId);
7834            if (next != null && next.includeForAccessibility()) {
7835                info.setTraversalAfter(next);
7836            }
7837        }
7838
7839        info.setVisibleToUser(isVisibleToUser());
7840
7841        info.setImportantForAccessibility(isImportantForAccessibility());
7842        info.setPackageName(mContext.getPackageName());
7843        info.setClassName(getAccessibilityClassName());
7844        info.setContentDescription(getContentDescription());
7845
7846        info.setEnabled(isEnabled());
7847        info.setClickable(isClickable());
7848        info.setFocusable(isFocusable());
7849        info.setFocused(isFocused());
7850        info.setAccessibilityFocused(isAccessibilityFocused());
7851        info.setSelected(isSelected());
7852        info.setLongClickable(isLongClickable());
7853        info.setContextClickable(isContextClickable());
7854        info.setLiveRegion(getAccessibilityLiveRegion());
7855
7856        // TODO: These make sense only if we are in an AdapterView but all
7857        // views can be selected. Maybe from accessibility perspective
7858        // we should report as selectable view in an AdapterView.
7859        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
7860        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
7861
7862        if (isFocusable()) {
7863            if (isFocused()) {
7864                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
7865            } else {
7866                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
7867            }
7868        }
7869
7870        if (!isAccessibilityFocused()) {
7871            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
7872        } else {
7873            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
7874        }
7875
7876        if (isClickable() && isEnabled()) {
7877            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
7878        }
7879
7880        if (isLongClickable() && isEnabled()) {
7881            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
7882        }
7883
7884        if (isContextClickable() && isEnabled()) {
7885            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
7886        }
7887
7888        CharSequence text = getIterableTextForAccessibility();
7889        if (text != null && text.length() > 0) {
7890            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
7891
7892            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
7893            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
7894            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
7895            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
7896                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
7897                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
7898        }
7899
7900        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
7901        populateAccessibilityNodeInfoDrawingOrderInParent(info);
7902    }
7903
7904    /**
7905     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
7906     * additional data.
7907     * <p>
7908     * This method only needs overloading if the node is marked as having extra data available.
7909     * </p>
7910     *
7911     * @param info The info to which to add the extra data. Never {@code null}.
7912     * @param extraDataKey A key specifying the type of extra data to add to the info. The
7913     *                     extra data should be added to the {@link Bundle} returned by
7914     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
7915     *                     {@code null}.
7916     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
7917     *                  {@code null} if the service provided no arguments.
7918     *
7919     * @see AccessibilityNodeInfo#setAvailableExtraData(List)
7920     */
7921    public void addExtraDataToAccessibilityNodeInfo(
7922            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
7923            @Nullable Bundle arguments) {
7924    }
7925
7926    /**
7927     * Determine the order in which this view will be drawn relative to its siblings for a11y
7928     *
7929     * @param info The info whose drawing order should be populated
7930     */
7931    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
7932        /*
7933         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
7934         * drawing order may not be well-defined, and some Views with custom drawing order may
7935         * not be initialized sufficiently to respond properly getChildDrawingOrder.
7936         */
7937        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
7938            info.setDrawingOrder(0);
7939            return;
7940        }
7941        int drawingOrderInParent = 1;
7942        // Iterate up the hierarchy if parents are not important for a11y
7943        View viewAtDrawingLevel = this;
7944        final ViewParent parent = getParentForAccessibility();
7945        while (viewAtDrawingLevel != parent) {
7946            final ViewParent currentParent = viewAtDrawingLevel.getParent();
7947            if (!(currentParent instanceof ViewGroup)) {
7948                // Should only happen for the Decor
7949                drawingOrderInParent = 0;
7950                break;
7951            } else {
7952                final ViewGroup parentGroup = (ViewGroup) currentParent;
7953                final int childCount = parentGroup.getChildCount();
7954                if (childCount > 1) {
7955                    List<View> preorderedList = parentGroup.buildOrderedChildList();
7956                    if (preorderedList != null) {
7957                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
7958                        for (int i = 0; i < childDrawIndex; i++) {
7959                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
7960                        }
7961                    } else {
7962                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
7963                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
7964                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
7965                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
7966                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
7967                        if (childDrawIndex != 0) {
7968                            for (int i = 0; i < numChildrenToIterate; i++) {
7969                                final int otherDrawIndex = (customOrder ?
7970                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
7971                                if (otherDrawIndex < childDrawIndex) {
7972                                    drawingOrderInParent +=
7973                                            numViewsForAccessibility(parentGroup.getChildAt(i));
7974                                }
7975                            }
7976                        }
7977                    }
7978                }
7979            }
7980            viewAtDrawingLevel = (View) currentParent;
7981        }
7982        info.setDrawingOrder(drawingOrderInParent);
7983    }
7984
7985    private static int numViewsForAccessibility(View view) {
7986        if (view != null) {
7987            if (view.includeForAccessibility()) {
7988                return 1;
7989            } else if (view instanceof ViewGroup) {
7990                return ((ViewGroup) view).getNumChildrenForAccessibility();
7991            }
7992        }
7993        return 0;
7994    }
7995
7996    private View findLabelForView(View view, int labeledId) {
7997        if (mMatchLabelForPredicate == null) {
7998            mMatchLabelForPredicate = new MatchLabelForPredicate();
7999        }
8000        mMatchLabelForPredicate.mLabeledId = labeledId;
8001        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
8002    }
8003
8004    /**
8005     * Computes whether this view is visible to the user. Such a view is
8006     * attached, visible, all its predecessors are visible, it is not clipped
8007     * entirely by its predecessors, and has an alpha greater than zero.
8008     *
8009     * @return Whether the view is visible on the screen.
8010     *
8011     * @hide
8012     */
8013    protected boolean isVisibleToUser() {
8014        return isVisibleToUser(null);
8015    }
8016
8017    /**
8018     * Computes whether the given portion of this view is visible to the user.
8019     * Such a view is attached, visible, all its predecessors are visible,
8020     * has an alpha greater than zero, and the specified portion is not
8021     * clipped entirely by its predecessors.
8022     *
8023     * @param boundInView the portion of the view to test; coordinates should be relative; may be
8024     *                    <code>null</code>, and the entire view will be tested in this case.
8025     *                    When <code>true</code> is returned by the function, the actual visible
8026     *                    region will be stored in this parameter; that is, if boundInView is fully
8027     *                    contained within the view, no modification will be made, otherwise regions
8028     *                    outside of the visible area of the view will be clipped.
8029     *
8030     * @return Whether the specified portion of the view is visible on the screen.
8031     *
8032     * @hide
8033     */
8034    protected boolean isVisibleToUser(Rect boundInView) {
8035        if (mAttachInfo != null) {
8036            // Attached to invisible window means this view is not visible.
8037            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8038                return false;
8039            }
8040            // An invisible predecessor or one with alpha zero means
8041            // that this view is not visible to the user.
8042            Object current = this;
8043            while (current instanceof View) {
8044                View view = (View) current;
8045                // We have attach info so this view is attached and there is no
8046                // need to check whether we reach to ViewRootImpl on the way up.
8047                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8048                        view.getVisibility() != VISIBLE) {
8049                    return false;
8050                }
8051                current = view.mParent;
8052            }
8053            // Check if the view is entirely covered by its predecessors.
8054            Rect visibleRect = mAttachInfo.mTmpInvalRect;
8055            Point offset = mAttachInfo.mPoint;
8056            if (!getGlobalVisibleRect(visibleRect, offset)) {
8057                return false;
8058            }
8059            // Check if the visible portion intersects the rectangle of interest.
8060            if (boundInView != null) {
8061                visibleRect.offset(-offset.x, -offset.y);
8062                return boundInView.intersect(visibleRect);
8063            }
8064            return true;
8065        }
8066        return false;
8067    }
8068
8069    /**
8070     * Returns the delegate for implementing accessibility support via
8071     * composition. For more details see {@link AccessibilityDelegate}.
8072     *
8073     * @return The delegate, or null if none set.
8074     *
8075     * @hide
8076     */
8077    public AccessibilityDelegate getAccessibilityDelegate() {
8078        return mAccessibilityDelegate;
8079    }
8080
8081    /**
8082     * Sets a delegate for implementing accessibility support via composition
8083     * (as opposed to inheritance). For more details, see
8084     * {@link AccessibilityDelegate}.
8085     * <p>
8086     * <strong>Note:</strong> On platform versions prior to
8087     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8088     * views in the {@code android.widget.*} package are called <i>before</i>
8089     * host methods. This prevents certain properties such as class name from
8090     * being modified by overriding
8091     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8092     * as any changes will be overwritten by the host class.
8093     * <p>
8094     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8095     * methods are called <i>after</i> host methods, which all properties to be
8096     * modified without being overwritten by the host class.
8097     *
8098     * @param delegate the object to which accessibility method calls should be
8099     *                 delegated
8100     * @see AccessibilityDelegate
8101     */
8102    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8103        mAccessibilityDelegate = delegate;
8104    }
8105
8106    /**
8107     * Gets the provider for managing a virtual view hierarchy rooted at this View
8108     * and reported to {@link android.accessibilityservice.AccessibilityService}s
8109     * that explore the window content.
8110     * <p>
8111     * If this method returns an instance, this instance is responsible for managing
8112     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8113     * View including the one representing the View itself. Similarly the returned
8114     * instance is responsible for performing accessibility actions on any virtual
8115     * view or the root view itself.
8116     * </p>
8117     * <p>
8118     * If an {@link AccessibilityDelegate} has been specified via calling
8119     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8120     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8121     * is responsible for handling this call.
8122     * </p>
8123     *
8124     * @return The provider.
8125     *
8126     * @see AccessibilityNodeProvider
8127     */
8128    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8129        if (mAccessibilityDelegate != null) {
8130            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8131        } else {
8132            return null;
8133        }
8134    }
8135
8136    /**
8137     * Gets the unique identifier of this view on the screen for accessibility purposes.
8138     *
8139     * @return The view accessibility id.
8140     *
8141     * @hide
8142     */
8143    public int getAccessibilityViewId() {
8144        if (mAccessibilityViewId == NO_ID) {
8145            mAccessibilityViewId = mContext.getNextAccessibilityId();
8146        }
8147        return mAccessibilityViewId;
8148    }
8149
8150    /**
8151     * Gets the unique identifier of the window in which this View reseides.
8152     *
8153     * @return The window accessibility id.
8154     *
8155     * @hide
8156     */
8157    public int getAccessibilityWindowId() {
8158        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8159                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8160    }
8161
8162    /**
8163     * Returns the {@link View}'s content description.
8164     * <p>
8165     * <strong>Note:</strong> Do not override this method, as it will have no
8166     * effect on the content description presented to accessibility services.
8167     * You must call {@link #setContentDescription(CharSequence)} to modify the
8168     * content description.
8169     *
8170     * @return the content description
8171     * @see #setContentDescription(CharSequence)
8172     * @attr ref android.R.styleable#View_contentDescription
8173     */
8174    @ViewDebug.ExportedProperty(category = "accessibility")
8175    public CharSequence getContentDescription() {
8176        return mContentDescription;
8177    }
8178
8179    /**
8180     * Sets the {@link View}'s content description.
8181     * <p>
8182     * A content description briefly describes the view and is primarily used
8183     * for accessibility support to determine how a view should be presented to
8184     * the user. In the case of a view with no textual representation, such as
8185     * {@link android.widget.ImageButton}, a useful content description
8186     * explains what the view does. For example, an image button with a phone
8187     * icon that is used to place a call may use "Call" as its content
8188     * description. An image of a floppy disk that is used to save a file may
8189     * use "Save".
8190     *
8191     * @param contentDescription The content description.
8192     * @see #getContentDescription()
8193     * @attr ref android.R.styleable#View_contentDescription
8194     */
8195    @RemotableViewMethod
8196    public void setContentDescription(CharSequence contentDescription) {
8197        if (mContentDescription == null) {
8198            if (contentDescription == null) {
8199                return;
8200            }
8201        } else if (mContentDescription.equals(contentDescription)) {
8202            return;
8203        }
8204        mContentDescription = contentDescription;
8205        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8206        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8207            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8208            notifySubtreeAccessibilityStateChangedIfNeeded();
8209        } else {
8210            notifyViewAccessibilityStateChangedIfNeeded(
8211                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8212        }
8213    }
8214
8215    /**
8216     * Sets the id of a view before which this one is visited in accessibility traversal.
8217     * A screen-reader must visit the content of this view before the content of the one
8218     * it precedes. For example, if view B is set to be before view A, then a screen-reader
8219     * will traverse the entire content of B before traversing the entire content of A,
8220     * regardles of what traversal strategy it is using.
8221     * <p>
8222     * Views that do not have specified before/after relationships are traversed in order
8223     * determined by the screen-reader.
8224     * </p>
8225     * <p>
8226     * Setting that this view is before a view that is not important for accessibility
8227     * or if this view is not important for accessibility will have no effect as the
8228     * screen-reader is not aware of unimportant views.
8229     * </p>
8230     *
8231     * @param beforeId The id of a view this one precedes in accessibility traversal.
8232     *
8233     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8234     *
8235     * @see #setImportantForAccessibility(int)
8236     */
8237    @RemotableViewMethod
8238    public void setAccessibilityTraversalBefore(int beforeId) {
8239        if (mAccessibilityTraversalBeforeId == beforeId) {
8240            return;
8241        }
8242        mAccessibilityTraversalBeforeId = beforeId;
8243        notifyViewAccessibilityStateChangedIfNeeded(
8244                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8245    }
8246
8247    /**
8248     * Gets the id of a view before which this one is visited in accessibility traversal.
8249     *
8250     * @return The id of a view this one precedes in accessibility traversal if
8251     *         specified, otherwise {@link #NO_ID}.
8252     *
8253     * @see #setAccessibilityTraversalBefore(int)
8254     */
8255    public int getAccessibilityTraversalBefore() {
8256        return mAccessibilityTraversalBeforeId;
8257    }
8258
8259    /**
8260     * Sets the id of a view after which this one is visited in accessibility traversal.
8261     * A screen-reader must visit the content of the other view before the content of this
8262     * one. For example, if view B is set to be after view A, then a screen-reader
8263     * will traverse the entire content of A before traversing the entire content of B,
8264     * regardles of what traversal strategy it is using.
8265     * <p>
8266     * Views that do not have specified before/after relationships are traversed in order
8267     * determined by the screen-reader.
8268     * </p>
8269     * <p>
8270     * Setting that this view is after a view that is not important for accessibility
8271     * or if this view is not important for accessibility will have no effect as the
8272     * screen-reader is not aware of unimportant views.
8273     * </p>
8274     *
8275     * @param afterId The id of a view this one succedees in accessibility traversal.
8276     *
8277     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8278     *
8279     * @see #setImportantForAccessibility(int)
8280     */
8281    @RemotableViewMethod
8282    public void setAccessibilityTraversalAfter(int afterId) {
8283        if (mAccessibilityTraversalAfterId == afterId) {
8284            return;
8285        }
8286        mAccessibilityTraversalAfterId = afterId;
8287        notifyViewAccessibilityStateChangedIfNeeded(
8288                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8289    }
8290
8291    /**
8292     * Gets the id of a view after which this one is visited in accessibility traversal.
8293     *
8294     * @return The id of a view this one succeedes in accessibility traversal if
8295     *         specified, otherwise {@link #NO_ID}.
8296     *
8297     * @see #setAccessibilityTraversalAfter(int)
8298     */
8299    public int getAccessibilityTraversalAfter() {
8300        return mAccessibilityTraversalAfterId;
8301    }
8302
8303    /**
8304     * Gets the id of a view for which this view serves as a label for
8305     * accessibility purposes.
8306     *
8307     * @return The labeled view id.
8308     */
8309    @ViewDebug.ExportedProperty(category = "accessibility")
8310    public int getLabelFor() {
8311        return mLabelForId;
8312    }
8313
8314    /**
8315     * Sets the id of a view for which this view serves as a label for
8316     * accessibility purposes.
8317     *
8318     * @param id The labeled view id.
8319     */
8320    @RemotableViewMethod
8321    public void setLabelFor(@IdRes int id) {
8322        if (mLabelForId == id) {
8323            return;
8324        }
8325        mLabelForId = id;
8326        if (mLabelForId != View.NO_ID
8327                && mID == View.NO_ID) {
8328            mID = generateViewId();
8329        }
8330        notifyViewAccessibilityStateChangedIfNeeded(
8331                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8332    }
8333
8334    /**
8335     * Invoked whenever this view loses focus, either by losing window focus or by losing
8336     * focus within its window. This method can be used to clear any state tied to the
8337     * focus. For instance, if a button is held pressed with the trackball and the window
8338     * loses focus, this method can be used to cancel the press.
8339     *
8340     * Subclasses of View overriding this method should always call super.onFocusLost().
8341     *
8342     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8343     * @see #onWindowFocusChanged(boolean)
8344     *
8345     * @hide pending API council approval
8346     */
8347    @CallSuper
8348    protected void onFocusLost() {
8349        resetPressedState();
8350    }
8351
8352    private void resetPressedState() {
8353        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8354            return;
8355        }
8356
8357        if (isPressed()) {
8358            setPressed(false);
8359
8360            if (!mHasPerformedLongPress) {
8361                removeLongPressCallback();
8362            }
8363        }
8364    }
8365
8366    /**
8367     * Returns true if this view has focus
8368     *
8369     * @return True if this view has focus, false otherwise.
8370     */
8371    @ViewDebug.ExportedProperty(category = "focus")
8372    public boolean isFocused() {
8373        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8374    }
8375
8376    /**
8377     * Find the view in the hierarchy rooted at this view that currently has
8378     * focus.
8379     *
8380     * @return The view that currently has focus, or null if no focused view can
8381     *         be found.
8382     */
8383    public View findFocus() {
8384        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8385    }
8386
8387    /**
8388     * Indicates whether this view is one of the set of scrollable containers in
8389     * its window.
8390     *
8391     * @return whether this view is one of the set of scrollable containers in
8392     * its window
8393     *
8394     * @attr ref android.R.styleable#View_isScrollContainer
8395     */
8396    public boolean isScrollContainer() {
8397        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8398    }
8399
8400    /**
8401     * Change whether this view is one of the set of scrollable containers in
8402     * its window.  This will be used to determine whether the window can
8403     * resize or must pan when a soft input area is open -- scrollable
8404     * containers allow the window to use resize mode since the container
8405     * will appropriately shrink.
8406     *
8407     * @attr ref android.R.styleable#View_isScrollContainer
8408     */
8409    public void setScrollContainer(boolean isScrollContainer) {
8410        if (isScrollContainer) {
8411            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8412                mAttachInfo.mScrollContainers.add(this);
8413                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8414            }
8415            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8416        } else {
8417            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8418                mAttachInfo.mScrollContainers.remove(this);
8419            }
8420            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8421        }
8422    }
8423
8424    /**
8425     * Returns the quality of the drawing cache.
8426     *
8427     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8428     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8429     *
8430     * @see #setDrawingCacheQuality(int)
8431     * @see #setDrawingCacheEnabled(boolean)
8432     * @see #isDrawingCacheEnabled()
8433     *
8434     * @attr ref android.R.styleable#View_drawingCacheQuality
8435     */
8436    @DrawingCacheQuality
8437    public int getDrawingCacheQuality() {
8438        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8439    }
8440
8441    /**
8442     * Set the drawing cache quality of this view. This value is used only when the
8443     * drawing cache is enabled
8444     *
8445     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8446     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8447     *
8448     * @see #getDrawingCacheQuality()
8449     * @see #setDrawingCacheEnabled(boolean)
8450     * @see #isDrawingCacheEnabled()
8451     *
8452     * @attr ref android.R.styleable#View_drawingCacheQuality
8453     */
8454    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8455        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8456    }
8457
8458    /**
8459     * Returns whether the screen should remain on, corresponding to the current
8460     * value of {@link #KEEP_SCREEN_ON}.
8461     *
8462     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8463     *
8464     * @see #setKeepScreenOn(boolean)
8465     *
8466     * @attr ref android.R.styleable#View_keepScreenOn
8467     */
8468    public boolean getKeepScreenOn() {
8469        return (mViewFlags & KEEP_SCREEN_ON) != 0;
8470    }
8471
8472    /**
8473     * Controls whether the screen should remain on, modifying the
8474     * value of {@link #KEEP_SCREEN_ON}.
8475     *
8476     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8477     *
8478     * @see #getKeepScreenOn()
8479     *
8480     * @attr ref android.R.styleable#View_keepScreenOn
8481     */
8482    public void setKeepScreenOn(boolean keepScreenOn) {
8483        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8484    }
8485
8486    /**
8487     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8488     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8489     *
8490     * @attr ref android.R.styleable#View_nextFocusLeft
8491     */
8492    public int getNextFocusLeftId() {
8493        return mNextFocusLeftId;
8494    }
8495
8496    /**
8497     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8498     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8499     * decide automatically.
8500     *
8501     * @attr ref android.R.styleable#View_nextFocusLeft
8502     */
8503    public void setNextFocusLeftId(int nextFocusLeftId) {
8504        mNextFocusLeftId = nextFocusLeftId;
8505    }
8506
8507    /**
8508     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8509     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8510     *
8511     * @attr ref android.R.styleable#View_nextFocusRight
8512     */
8513    public int getNextFocusRightId() {
8514        return mNextFocusRightId;
8515    }
8516
8517    /**
8518     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8519     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8520     * decide automatically.
8521     *
8522     * @attr ref android.R.styleable#View_nextFocusRight
8523     */
8524    public void setNextFocusRightId(int nextFocusRightId) {
8525        mNextFocusRightId = nextFocusRightId;
8526    }
8527
8528    /**
8529     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8530     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8531     *
8532     * @attr ref android.R.styleable#View_nextFocusUp
8533     */
8534    public int getNextFocusUpId() {
8535        return mNextFocusUpId;
8536    }
8537
8538    /**
8539     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8540     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8541     * decide automatically.
8542     *
8543     * @attr ref android.R.styleable#View_nextFocusUp
8544     */
8545    public void setNextFocusUpId(int nextFocusUpId) {
8546        mNextFocusUpId = nextFocusUpId;
8547    }
8548
8549    /**
8550     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8551     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8552     *
8553     * @attr ref android.R.styleable#View_nextFocusDown
8554     */
8555    public int getNextFocusDownId() {
8556        return mNextFocusDownId;
8557    }
8558
8559    /**
8560     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8561     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8562     * decide automatically.
8563     *
8564     * @attr ref android.R.styleable#View_nextFocusDown
8565     */
8566    public void setNextFocusDownId(int nextFocusDownId) {
8567        mNextFocusDownId = nextFocusDownId;
8568    }
8569
8570    /**
8571     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8572     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8573     *
8574     * @attr ref android.R.styleable#View_nextFocusForward
8575     */
8576    public int getNextFocusForwardId() {
8577        return mNextFocusForwardId;
8578    }
8579
8580    /**
8581     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8582     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8583     * decide automatically.
8584     *
8585     * @attr ref android.R.styleable#View_nextFocusForward
8586     */
8587    public void setNextFocusForwardId(int nextFocusForwardId) {
8588        mNextFocusForwardId = nextFocusForwardId;
8589    }
8590
8591    /**
8592     * Gets the id of the root of the next keyboard navigation cluster.
8593     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8594     * decide automatically.
8595     *
8596     * @attr ref android.R.styleable#View_nextClusterForward
8597     */
8598    public int getNextClusterForwardId() {
8599        return mNextClusterForwardId;
8600    }
8601
8602    /**
8603     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8604     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8605     * decide automatically.
8606     *
8607     * @attr ref android.R.styleable#View_nextClusterForward
8608     */
8609    public void setNextClusterForwardId(int nextClusterForwardId) {
8610        mNextClusterForwardId = nextClusterForwardId;
8611    }
8612
8613    /**
8614     * Returns the visibility of this view and all of its ancestors
8615     *
8616     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8617     */
8618    public boolean isShown() {
8619        View current = this;
8620        //noinspection ConstantConditions
8621        do {
8622            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8623                return false;
8624            }
8625            ViewParent parent = current.mParent;
8626            if (parent == null) {
8627                return false; // We are not attached to the view root
8628            }
8629            if (!(parent instanceof View)) {
8630                return true;
8631            }
8632            current = (View) parent;
8633        } while (current != null);
8634
8635        return false;
8636    }
8637
8638    /**
8639     * Called by the view hierarchy when the content insets for a window have
8640     * changed, to allow it to adjust its content to fit within those windows.
8641     * The content insets tell you the space that the status bar, input method,
8642     * and other system windows infringe on the application's window.
8643     *
8644     * <p>You do not normally need to deal with this function, since the default
8645     * window decoration given to applications takes care of applying it to the
8646     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
8647     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
8648     * and your content can be placed under those system elements.  You can then
8649     * use this method within your view hierarchy if you have parts of your UI
8650     * which you would like to ensure are not being covered.
8651     *
8652     * <p>The default implementation of this method simply applies the content
8653     * insets to the view's padding, consuming that content (modifying the
8654     * insets to be 0), and returning true.  This behavior is off by default, but can
8655     * be enabled through {@link #setFitsSystemWindows(boolean)}.
8656     *
8657     * <p>This function's traversal down the hierarchy is depth-first.  The same content
8658     * insets object is propagated down the hierarchy, so any changes made to it will
8659     * be seen by all following views (including potentially ones above in
8660     * the hierarchy since this is a depth-first traversal).  The first view
8661     * that returns true will abort the entire traversal.
8662     *
8663     * <p>The default implementation works well for a situation where it is
8664     * used with a container that covers the entire window, allowing it to
8665     * apply the appropriate insets to its content on all edges.  If you need
8666     * a more complicated layout (such as two different views fitting system
8667     * windows, one on the top of the window, and one on the bottom),
8668     * you can override the method and handle the insets however you would like.
8669     * Note that the insets provided by the framework are always relative to the
8670     * far edges of the window, not accounting for the location of the called view
8671     * within that window.  (In fact when this method is called you do not yet know
8672     * where the layout will place the view, as it is done before layout happens.)
8673     *
8674     * <p>Note: unlike many View methods, there is no dispatch phase to this
8675     * call.  If you are overriding it in a ViewGroup and want to allow the
8676     * call to continue to your children, you must be sure to call the super
8677     * implementation.
8678     *
8679     * <p>Here is a sample layout that makes use of fitting system windows
8680     * to have controls for a video view placed inside of the window decorations
8681     * that it hides and shows.  This can be used with code like the second
8682     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
8683     *
8684     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
8685     *
8686     * @param insets Current content insets of the window.  Prior to
8687     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
8688     * the insets or else you and Android will be unhappy.
8689     *
8690     * @return {@code true} if this view applied the insets and it should not
8691     * continue propagating further down the hierarchy, {@code false} otherwise.
8692     * @see #getFitsSystemWindows()
8693     * @see #setFitsSystemWindows(boolean)
8694     * @see #setSystemUiVisibility(int)
8695     *
8696     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
8697     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
8698     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
8699     * to implement handling their own insets.
8700     */
8701    @Deprecated
8702    protected boolean fitSystemWindows(Rect insets) {
8703        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
8704            if (insets == null) {
8705                // Null insets by definition have already been consumed.
8706                // This call cannot apply insets since there are none to apply,
8707                // so return false.
8708                return false;
8709            }
8710            // If we're not in the process of dispatching the newer apply insets call,
8711            // that means we're not in the compatibility path. Dispatch into the newer
8712            // apply insets path and take things from there.
8713            try {
8714                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
8715                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
8716            } finally {
8717                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
8718            }
8719        } else {
8720            // We're being called from the newer apply insets path.
8721            // Perform the standard fallback behavior.
8722            return fitSystemWindowsInt(insets);
8723        }
8724    }
8725
8726    private boolean fitSystemWindowsInt(Rect insets) {
8727        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
8728            mUserPaddingStart = UNDEFINED_PADDING;
8729            mUserPaddingEnd = UNDEFINED_PADDING;
8730            Rect localInsets = sThreadLocal.get();
8731            if (localInsets == null) {
8732                localInsets = new Rect();
8733                sThreadLocal.set(localInsets);
8734            }
8735            boolean res = computeFitSystemWindows(insets, localInsets);
8736            mUserPaddingLeftInitial = localInsets.left;
8737            mUserPaddingRightInitial = localInsets.right;
8738            internalSetPadding(localInsets.left, localInsets.top,
8739                    localInsets.right, localInsets.bottom);
8740            return res;
8741        }
8742        return false;
8743    }
8744
8745    /**
8746     * Called when the view should apply {@link WindowInsets} according to its internal policy.
8747     *
8748     * <p>This method should be overridden by views that wish to apply a policy different from or
8749     * in addition to the default behavior. Clients that wish to force a view subtree
8750     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
8751     *
8752     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
8753     * it will be called during dispatch instead of this method. The listener may optionally
8754     * call this method from its own implementation if it wishes to apply the view's default
8755     * insets policy in addition to its own.</p>
8756     *
8757     * <p>Implementations of this method should either return the insets parameter unchanged
8758     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
8759     * that this view applied itself. This allows new inset types added in future platform
8760     * versions to pass through existing implementations unchanged without being erroneously
8761     * consumed.</p>
8762     *
8763     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
8764     * property is set then the view will consume the system window insets and apply them
8765     * as padding for the view.</p>
8766     *
8767     * @param insets Insets to apply
8768     * @return The supplied insets with any applied insets consumed
8769     */
8770    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
8771        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
8772            // We weren't called from within a direct call to fitSystemWindows,
8773            // call into it as a fallback in case we're in a class that overrides it
8774            // and has logic to perform.
8775            if (fitSystemWindows(insets.getSystemWindowInsets())) {
8776                return insets.consumeSystemWindowInsets();
8777            }
8778        } else {
8779            // We were called from within a direct call to fitSystemWindows.
8780            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
8781                return insets.consumeSystemWindowInsets();
8782            }
8783        }
8784        return insets;
8785    }
8786
8787    /**
8788     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
8789     * window insets to this view. The listener's
8790     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
8791     * method will be called instead of the view's
8792     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
8793     *
8794     * @param listener Listener to set
8795     *
8796     * @see #onApplyWindowInsets(WindowInsets)
8797     */
8798    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
8799        getListenerInfo().mOnApplyWindowInsetsListener = listener;
8800    }
8801
8802    /**
8803     * Request to apply the given window insets to this view or another view in its subtree.
8804     *
8805     * <p>This method should be called by clients wishing to apply insets corresponding to areas
8806     * obscured by window decorations or overlays. This can include the status and navigation bars,
8807     * action bars, input methods and more. New inset categories may be added in the future.
8808     * The method returns the insets provided minus any that were applied by this view or its
8809     * children.</p>
8810     *
8811     * <p>Clients wishing to provide custom behavior should override the
8812     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
8813     * {@link OnApplyWindowInsetsListener} via the
8814     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
8815     * method.</p>
8816     *
8817     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
8818     * </p>
8819     *
8820     * @param insets Insets to apply
8821     * @return The provided insets minus the insets that were consumed
8822     */
8823    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
8824        try {
8825            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
8826            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
8827                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
8828            } else {
8829                return onApplyWindowInsets(insets);
8830            }
8831        } finally {
8832            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
8833        }
8834    }
8835
8836    /**
8837     * Compute the view's coordinate within the surface.
8838     *
8839     * <p>Computes the coordinates of this view in its surface. The argument
8840     * must be an array of two integers. After the method returns, the array
8841     * contains the x and y location in that order.</p>
8842     * @hide
8843     * @param location an array of two integers in which to hold the coordinates
8844     */
8845    public void getLocationInSurface(@Size(2) int[] location) {
8846        getLocationInWindow(location);
8847        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
8848            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
8849            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
8850        }
8851    }
8852
8853    /**
8854     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
8855     * only available if the view is attached.
8856     *
8857     * @return WindowInsets from the top of the view hierarchy or null if View is detached
8858     */
8859    public WindowInsets getRootWindowInsets() {
8860        if (mAttachInfo != null) {
8861            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
8862        }
8863        return null;
8864    }
8865
8866    /**
8867     * @hide Compute the insets that should be consumed by this view and the ones
8868     * that should propagate to those under it.
8869     */
8870    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
8871        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8872                || mAttachInfo == null
8873                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
8874                        && !mAttachInfo.mOverscanRequested)) {
8875            outLocalInsets.set(inoutInsets);
8876            inoutInsets.set(0, 0, 0, 0);
8877            return true;
8878        } else {
8879            // The application wants to take care of fitting system window for
8880            // the content...  however we still need to take care of any overscan here.
8881            final Rect overscan = mAttachInfo.mOverscanInsets;
8882            outLocalInsets.set(overscan);
8883            inoutInsets.left -= overscan.left;
8884            inoutInsets.top -= overscan.top;
8885            inoutInsets.right -= overscan.right;
8886            inoutInsets.bottom -= overscan.bottom;
8887            return false;
8888        }
8889    }
8890
8891    /**
8892     * Compute insets that should be consumed by this view and the ones that should propagate
8893     * to those under it.
8894     *
8895     * @param in Insets currently being processed by this View, likely received as a parameter
8896     *           to {@link #onApplyWindowInsets(WindowInsets)}.
8897     * @param outLocalInsets A Rect that will receive the insets that should be consumed
8898     *                       by this view
8899     * @return Insets that should be passed along to views under this one
8900     */
8901    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
8902        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
8903                || mAttachInfo == null
8904                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
8905            outLocalInsets.set(in.getSystemWindowInsets());
8906            return in.consumeSystemWindowInsets();
8907        } else {
8908            outLocalInsets.set(0, 0, 0, 0);
8909            return in;
8910        }
8911    }
8912
8913    /**
8914     * Sets whether or not this view should account for system screen decorations
8915     * such as the status bar and inset its content; that is, controlling whether
8916     * the default implementation of {@link #fitSystemWindows(Rect)} will be
8917     * executed.  See that method for more details.
8918     *
8919     * <p>Note that if you are providing your own implementation of
8920     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
8921     * flag to true -- your implementation will be overriding the default
8922     * implementation that checks this flag.
8923     *
8924     * @param fitSystemWindows If true, then the default implementation of
8925     * {@link #fitSystemWindows(Rect)} will be executed.
8926     *
8927     * @attr ref android.R.styleable#View_fitsSystemWindows
8928     * @see #getFitsSystemWindows()
8929     * @see #fitSystemWindows(Rect)
8930     * @see #setSystemUiVisibility(int)
8931     */
8932    public void setFitsSystemWindows(boolean fitSystemWindows) {
8933        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
8934    }
8935
8936    /**
8937     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
8938     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
8939     * will be executed.
8940     *
8941     * @return {@code true} if the default implementation of
8942     * {@link #fitSystemWindows(Rect)} will be executed.
8943     *
8944     * @attr ref android.R.styleable#View_fitsSystemWindows
8945     * @see #setFitsSystemWindows(boolean)
8946     * @see #fitSystemWindows(Rect)
8947     * @see #setSystemUiVisibility(int)
8948     */
8949    @ViewDebug.ExportedProperty
8950    public boolean getFitsSystemWindows() {
8951        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
8952    }
8953
8954    /** @hide */
8955    public boolean fitsSystemWindows() {
8956        return getFitsSystemWindows();
8957    }
8958
8959    /**
8960     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
8961     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
8962     */
8963    @Deprecated
8964    public void requestFitSystemWindows() {
8965        if (mParent != null) {
8966            mParent.requestFitSystemWindows();
8967        }
8968    }
8969
8970    /**
8971     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
8972     */
8973    public void requestApplyInsets() {
8974        requestFitSystemWindows();
8975    }
8976
8977    /**
8978     * For use by PhoneWindow to make its own system window fitting optional.
8979     * @hide
8980     */
8981    public void makeOptionalFitsSystemWindows() {
8982        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
8983    }
8984
8985    /**
8986     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
8987     * treat them as such.
8988     * @hide
8989     */
8990    public void getOutsets(Rect outOutsetRect) {
8991        if (mAttachInfo != null) {
8992            outOutsetRect.set(mAttachInfo.mOutsets);
8993        } else {
8994            outOutsetRect.setEmpty();
8995        }
8996    }
8997
8998    /**
8999     * Returns the visibility status for this view.
9000     *
9001     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9002     * @attr ref android.R.styleable#View_visibility
9003     */
9004    @ViewDebug.ExportedProperty(mapping = {
9005        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
9006        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
9007        @ViewDebug.IntToString(from = GONE,      to = "GONE")
9008    })
9009    @Visibility
9010    public int getVisibility() {
9011        return mViewFlags & VISIBILITY_MASK;
9012    }
9013
9014    /**
9015     * Set the visibility state of this view.
9016     *
9017     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9018     * @attr ref android.R.styleable#View_visibility
9019     */
9020    @RemotableViewMethod
9021    public void setVisibility(@Visibility int visibility) {
9022        setFlags(visibility, VISIBILITY_MASK);
9023    }
9024
9025    /**
9026     * Returns the enabled status for this view. The interpretation of the
9027     * enabled state varies by subclass.
9028     *
9029     * @return True if this view is enabled, false otherwise.
9030     */
9031    @ViewDebug.ExportedProperty
9032    public boolean isEnabled() {
9033        return (mViewFlags & ENABLED_MASK) == ENABLED;
9034    }
9035
9036    /**
9037     * Set the enabled state of this view. The interpretation of the enabled
9038     * state varies by subclass.
9039     *
9040     * @param enabled True if this view is enabled, false otherwise.
9041     */
9042    @RemotableViewMethod
9043    public void setEnabled(boolean enabled) {
9044        if (enabled == isEnabled()) return;
9045
9046        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9047
9048        /*
9049         * The View most likely has to change its appearance, so refresh
9050         * the drawable state.
9051         */
9052        refreshDrawableState();
9053
9054        // Invalidate too, since the default behavior for views is to be
9055        // be drawn at 50% alpha rather than to change the drawable.
9056        invalidate(true);
9057
9058        if (!enabled) {
9059            cancelPendingInputEvents();
9060        }
9061    }
9062
9063    /**
9064     * Set whether this view can receive the focus.
9065     * <p>
9066     * Setting this to false will also ensure that this view is not focusable
9067     * in touch mode.
9068     *
9069     * @param focusable If true, this view can receive the focus.
9070     *
9071     * @see #setFocusableInTouchMode(boolean)
9072     * @see #setFocusable(int)
9073     * @attr ref android.R.styleable#View_focusable
9074     */
9075    public void setFocusable(boolean focusable) {
9076        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9077    }
9078
9079    /**
9080     * Sets whether this view can receive focus.
9081     * <p>
9082     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9083     * automatically based on the view's interactivity. This is the default.
9084     * <p>
9085     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9086     * in touch mode.
9087     *
9088     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9089     *                  or {@link #FOCUSABLE_AUTO}.
9090     * @see #setFocusableInTouchMode(boolean)
9091     * @attr ref android.R.styleable#View_focusable
9092     */
9093    public void setFocusable(@Focusable int focusable) {
9094        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9095            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9096        }
9097        setFlags(focusable, FOCUSABLE_MASK);
9098    }
9099
9100    /**
9101     * Set whether this view can receive focus while in touch mode.
9102     *
9103     * Setting this to true will also ensure that this view is focusable.
9104     *
9105     * @param focusableInTouchMode If true, this view can receive the focus while
9106     *   in touch mode.
9107     *
9108     * @see #setFocusable(boolean)
9109     * @attr ref android.R.styleable#View_focusableInTouchMode
9110     */
9111    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9112        // Focusable in touch mode should always be set before the focusable flag
9113        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9114        // which, in touch mode, will not successfully request focus on this view
9115        // because the focusable in touch mode flag is not set
9116        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9117
9118        // Clear FOCUSABLE_AUTO if set.
9119        if (focusableInTouchMode) {
9120            // Clears FOCUSABLE_AUTO if set.
9121            setFlags(FOCUSABLE, FOCUSABLE_MASK);
9122        }
9123    }
9124
9125    /**
9126     * Sets the hints that helps the autofill service to select the appropriate data to fill the
9127     * view.
9128     *
9129     * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
9130     * @attr ref android.R.styleable#View_autofillHints
9131     */
9132    public void setAutofillHints(@Nullable String... autofillHints) {
9133        if (autofillHints == null || autofillHints.length == 0) {
9134            mAutofillHints = null;
9135        } else {
9136            mAutofillHints = autofillHints;
9137        }
9138    }
9139
9140    /**
9141     * @hide
9142     */
9143    @TestApi
9144    public void setAutofilled(boolean isAutofilled) {
9145        boolean wasChanged = isAutofilled != isAutofilled();
9146
9147        if (wasChanged) {
9148            if (isAutofilled) {
9149                mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
9150            } else {
9151                mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
9152            }
9153
9154            invalidate();
9155        }
9156    }
9157
9158    /**
9159     * Set whether this view should have sound effects enabled for events such as
9160     * clicking and touching.
9161     *
9162     * <p>You may wish to disable sound effects for a view if you already play sounds,
9163     * for instance, a dial key that plays dtmf tones.
9164     *
9165     * @param soundEffectsEnabled whether sound effects are enabled for this view.
9166     * @see #isSoundEffectsEnabled()
9167     * @see #playSoundEffect(int)
9168     * @attr ref android.R.styleable#View_soundEffectsEnabled
9169     */
9170    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9171        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9172    }
9173
9174    /**
9175     * @return whether this view should have sound effects enabled for events such as
9176     *     clicking and touching.
9177     *
9178     * @see #setSoundEffectsEnabled(boolean)
9179     * @see #playSoundEffect(int)
9180     * @attr ref android.R.styleable#View_soundEffectsEnabled
9181     */
9182    @ViewDebug.ExportedProperty
9183    public boolean isSoundEffectsEnabled() {
9184        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9185    }
9186
9187    /**
9188     * Set whether this view should have haptic feedback for events such as
9189     * long presses.
9190     *
9191     * <p>You may wish to disable haptic feedback if your view already controls
9192     * its own haptic feedback.
9193     *
9194     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9195     * @see #isHapticFeedbackEnabled()
9196     * @see #performHapticFeedback(int)
9197     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9198     */
9199    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9200        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9201    }
9202
9203    /**
9204     * @return whether this view should have haptic feedback enabled for events
9205     * long presses.
9206     *
9207     * @see #setHapticFeedbackEnabled(boolean)
9208     * @see #performHapticFeedback(int)
9209     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9210     */
9211    @ViewDebug.ExportedProperty
9212    public boolean isHapticFeedbackEnabled() {
9213        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9214    }
9215
9216    /**
9217     * Returns the layout direction for this view.
9218     *
9219     * @return One of {@link #LAYOUT_DIRECTION_LTR},
9220     *   {@link #LAYOUT_DIRECTION_RTL},
9221     *   {@link #LAYOUT_DIRECTION_INHERIT} or
9222     *   {@link #LAYOUT_DIRECTION_LOCALE}.
9223     *
9224     * @attr ref android.R.styleable#View_layoutDirection
9225     *
9226     * @hide
9227     */
9228    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9229        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9230        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9231        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9232        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9233    })
9234    @LayoutDir
9235    public int getRawLayoutDirection() {
9236        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9237    }
9238
9239    /**
9240     * Set the layout direction for this view. This will propagate a reset of layout direction
9241     * resolution to the view's children and resolve layout direction for this view.
9242     *
9243     * @param layoutDirection the layout direction to set. Should be one of:
9244     *
9245     * {@link #LAYOUT_DIRECTION_LTR},
9246     * {@link #LAYOUT_DIRECTION_RTL},
9247     * {@link #LAYOUT_DIRECTION_INHERIT},
9248     * {@link #LAYOUT_DIRECTION_LOCALE}.
9249     *
9250     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9251     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9252     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9253     *
9254     * @attr ref android.R.styleable#View_layoutDirection
9255     */
9256    @RemotableViewMethod
9257    public void setLayoutDirection(@LayoutDir int layoutDirection) {
9258        if (getRawLayoutDirection() != layoutDirection) {
9259            // Reset the current layout direction and the resolved one
9260            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9261            resetRtlProperties();
9262            // Set the new layout direction (filtered)
9263            mPrivateFlags2 |=
9264                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9265            // We need to resolve all RTL properties as they all depend on layout direction
9266            resolveRtlPropertiesIfNeeded();
9267            requestLayout();
9268            invalidate(true);
9269        }
9270    }
9271
9272    /**
9273     * Returns the resolved layout direction for this view.
9274     *
9275     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9276     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9277     *
9278     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9279     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9280     *
9281     * @attr ref android.R.styleable#View_layoutDirection
9282     */
9283    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9284        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9285        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9286    })
9287    @ResolvedLayoutDir
9288    public int getLayoutDirection() {
9289        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9290        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9291            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9292            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9293        }
9294        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9295                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9296    }
9297
9298    /**
9299     * Indicates whether or not this view's layout is right-to-left. This is resolved from
9300     * layout attribute and/or the inherited value from the parent
9301     *
9302     * @return true if the layout is right-to-left.
9303     *
9304     * @hide
9305     */
9306    @ViewDebug.ExportedProperty(category = "layout")
9307    public boolean isLayoutRtl() {
9308        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9309    }
9310
9311    /**
9312     * Indicates whether the view is currently tracking transient state that the
9313     * app should not need to concern itself with saving and restoring, but that
9314     * the framework should take special note to preserve when possible.
9315     *
9316     * <p>A view with transient state cannot be trivially rebound from an external
9317     * data source, such as an adapter binding item views in a list. This may be
9318     * because the view is performing an animation, tracking user selection
9319     * of content, or similar.</p>
9320     *
9321     * @return true if the view has transient state
9322     */
9323    @ViewDebug.ExportedProperty(category = "layout")
9324    public boolean hasTransientState() {
9325        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9326    }
9327
9328    /**
9329     * Set whether this view is currently tracking transient state that the
9330     * framework should attempt to preserve when possible. This flag is reference counted,
9331     * so every call to setHasTransientState(true) should be paired with a later call
9332     * to setHasTransientState(false).
9333     *
9334     * <p>A view with transient state cannot be trivially rebound from an external
9335     * data source, such as an adapter binding item views in a list. This may be
9336     * because the view is performing an animation, tracking user selection
9337     * of content, or similar.</p>
9338     *
9339     * @param hasTransientState true if this view has transient state
9340     */
9341    public void setHasTransientState(boolean hasTransientState) {
9342        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9343                mTransientStateCount - 1;
9344        if (mTransientStateCount < 0) {
9345            mTransientStateCount = 0;
9346            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9347                    "unmatched pair of setHasTransientState calls");
9348        } else if ((hasTransientState && mTransientStateCount == 1) ||
9349                (!hasTransientState && mTransientStateCount == 0)) {
9350            // update flag if we've just incremented up from 0 or decremented down to 0
9351            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9352                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9353            if (mParent != null) {
9354                try {
9355                    mParent.childHasTransientStateChanged(this, hasTransientState);
9356                } catch (AbstractMethodError e) {
9357                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9358                            " does not fully implement ViewParent", e);
9359                }
9360            }
9361        }
9362    }
9363
9364    /**
9365     * Returns true if this view is currently attached to a window.
9366     */
9367    public boolean isAttachedToWindow() {
9368        return mAttachInfo != null;
9369    }
9370
9371    /**
9372     * Returns true if this view has been through at least one layout since it
9373     * was last attached to or detached from a window.
9374     */
9375    public boolean isLaidOut() {
9376        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9377    }
9378
9379    /**
9380     * If this view doesn't do any drawing on its own, set this flag to
9381     * allow further optimizations. By default, this flag is not set on
9382     * View, but could be set on some View subclasses such as ViewGroup.
9383     *
9384     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9385     * you should clear this flag.
9386     *
9387     * @param willNotDraw whether or not this View draw on its own
9388     */
9389    public void setWillNotDraw(boolean willNotDraw) {
9390        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9391    }
9392
9393    /**
9394     * Returns whether or not this View draws on its own.
9395     *
9396     * @return true if this view has nothing to draw, false otherwise
9397     */
9398    @ViewDebug.ExportedProperty(category = "drawing")
9399    public boolean willNotDraw() {
9400        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9401    }
9402
9403    /**
9404     * When a View's drawing cache is enabled, drawing is redirected to an
9405     * offscreen bitmap. Some views, like an ImageView, must be able to
9406     * bypass this mechanism if they already draw a single bitmap, to avoid
9407     * unnecessary usage of the memory.
9408     *
9409     * @param willNotCacheDrawing true if this view does not cache its
9410     *        drawing, false otherwise
9411     */
9412    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9413        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9414    }
9415
9416    /**
9417     * Returns whether or not this View can cache its drawing or not.
9418     *
9419     * @return true if this view does not cache its drawing, false otherwise
9420     */
9421    @ViewDebug.ExportedProperty(category = "drawing")
9422    public boolean willNotCacheDrawing() {
9423        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9424    }
9425
9426    /**
9427     * Indicates whether this view reacts to click events or not.
9428     *
9429     * @return true if the view is clickable, false otherwise
9430     *
9431     * @see #setClickable(boolean)
9432     * @attr ref android.R.styleable#View_clickable
9433     */
9434    @ViewDebug.ExportedProperty
9435    public boolean isClickable() {
9436        return (mViewFlags & CLICKABLE) == CLICKABLE;
9437    }
9438
9439    /**
9440     * Enables or disables click events for this view. When a view
9441     * is clickable it will change its state to "pressed" on every click.
9442     * Subclasses should set the view clickable to visually react to
9443     * user's clicks.
9444     *
9445     * @param clickable true to make the view clickable, false otherwise
9446     *
9447     * @see #isClickable()
9448     * @attr ref android.R.styleable#View_clickable
9449     */
9450    public void setClickable(boolean clickable) {
9451        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9452    }
9453
9454    /**
9455     * Indicates whether this view reacts to long click events or not.
9456     *
9457     * @return true if the view is long clickable, false otherwise
9458     *
9459     * @see #setLongClickable(boolean)
9460     * @attr ref android.R.styleable#View_longClickable
9461     */
9462    public boolean isLongClickable() {
9463        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9464    }
9465
9466    /**
9467     * Enables or disables long click events for this view. When a view is long
9468     * clickable it reacts to the user holding down the button for a longer
9469     * duration than a tap. This event can either launch the listener or a
9470     * context menu.
9471     *
9472     * @param longClickable true to make the view long clickable, false otherwise
9473     * @see #isLongClickable()
9474     * @attr ref android.R.styleable#View_longClickable
9475     */
9476    public void setLongClickable(boolean longClickable) {
9477        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9478    }
9479
9480    /**
9481     * Indicates whether this view reacts to context clicks or not.
9482     *
9483     * @return true if the view is context clickable, false otherwise
9484     * @see #setContextClickable(boolean)
9485     * @attr ref android.R.styleable#View_contextClickable
9486     */
9487    public boolean isContextClickable() {
9488        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9489    }
9490
9491    /**
9492     * Enables or disables context clicking for this view. This event can launch the listener.
9493     *
9494     * @param contextClickable true to make the view react to a context click, false otherwise
9495     * @see #isContextClickable()
9496     * @attr ref android.R.styleable#View_contextClickable
9497     */
9498    public void setContextClickable(boolean contextClickable) {
9499        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9500    }
9501
9502    /**
9503     * Sets the pressed state for this view and provides a touch coordinate for
9504     * animation hinting.
9505     *
9506     * @param pressed Pass true to set the View's internal state to "pressed",
9507     *            or false to reverts the View's internal state from a
9508     *            previously set "pressed" state.
9509     * @param x The x coordinate of the touch that caused the press
9510     * @param y The y coordinate of the touch that caused the press
9511     */
9512    private void setPressed(boolean pressed, float x, float y) {
9513        if (pressed) {
9514            drawableHotspotChanged(x, y);
9515        }
9516
9517        setPressed(pressed);
9518    }
9519
9520    /**
9521     * Sets the pressed state for this view.
9522     *
9523     * @see #isClickable()
9524     * @see #setClickable(boolean)
9525     *
9526     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9527     *        the View's internal state from a previously set "pressed" state.
9528     */
9529    public void setPressed(boolean pressed) {
9530        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9531
9532        if (pressed) {
9533            mPrivateFlags |= PFLAG_PRESSED;
9534        } else {
9535            mPrivateFlags &= ~PFLAG_PRESSED;
9536        }
9537
9538        if (needsRefresh) {
9539            refreshDrawableState();
9540        }
9541        dispatchSetPressed(pressed);
9542    }
9543
9544    /**
9545     * Dispatch setPressed to all of this View's children.
9546     *
9547     * @see #setPressed(boolean)
9548     *
9549     * @param pressed The new pressed state
9550     */
9551    protected void dispatchSetPressed(boolean pressed) {
9552    }
9553
9554    /**
9555     * Indicates whether the view is currently in pressed state. Unless
9556     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9557     * the pressed state.
9558     *
9559     * @see #setPressed(boolean)
9560     * @see #isClickable()
9561     * @see #setClickable(boolean)
9562     *
9563     * @return true if the view is currently pressed, false otherwise
9564     */
9565    @ViewDebug.ExportedProperty
9566    public boolean isPressed() {
9567        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9568    }
9569
9570    /**
9571     * @hide
9572     * Indicates whether this view will participate in data collection through
9573     * {@link ViewStructure}.  If true, it will not provide any data
9574     * for itself or its children.  If false, the normal data collection will be allowed.
9575     *
9576     * @return Returns false if assist data collection is not blocked, else true.
9577     *
9578     * @see #setAssistBlocked(boolean)
9579     * @attr ref android.R.styleable#View_assistBlocked
9580     */
9581    public boolean isAssistBlocked() {
9582        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9583    }
9584
9585    /**
9586     * @hide
9587     * Indicates whether this view will participate in data collection through
9588     * {@link ViewStructure} for autofill purposes.
9589     *
9590     * <p>If {@code true}, it will not provide any data for itself or its children.
9591     * <p>If {@code false}, the normal data collection will be allowed.
9592     *
9593     * @return Returns {@code false} if assist data collection for autofill is not blocked,
9594     * else {@code true}.
9595     *
9596     * TODO(b/33197203): update / remove javadoc tags below
9597     * @see #setAssistBlocked(boolean)
9598     * @attr ref android.R.styleable#View_assistBlocked
9599     */
9600    public boolean isAutofillBlocked() {
9601        return false; // TODO(b/33197203): properly implement it
9602    }
9603
9604    /**
9605     * @hide
9606     * Controls whether assist data collection from this view and its children is enabled
9607     * (that is, whether {@link #onProvideStructure} and
9608     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9609     * allowing normal assist collection.  Setting this to false will disable assist collection.
9610     *
9611     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9612     * (the default) to allow it.
9613     *
9614     * @see #isAssistBlocked()
9615     * @see #onProvideStructure
9616     * @see #onProvideVirtualStructure
9617     * @attr ref android.R.styleable#View_assistBlocked
9618     */
9619    public void setAssistBlocked(boolean enabled) {
9620        if (enabled) {
9621            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9622        } else {
9623            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9624        }
9625    }
9626
9627    /**
9628     * Indicates whether this view will save its state (that is,
9629     * whether its {@link #onSaveInstanceState} method will be called).
9630     *
9631     * @return Returns true if the view state saving is enabled, else false.
9632     *
9633     * @see #setSaveEnabled(boolean)
9634     * @attr ref android.R.styleable#View_saveEnabled
9635     */
9636    public boolean isSaveEnabled() {
9637        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9638    }
9639
9640    /**
9641     * Controls whether the saving of this view's state is
9642     * enabled (that is, whether its {@link #onSaveInstanceState} method
9643     * will be called).  Note that even if freezing is enabled, the
9644     * view still must have an id assigned to it (via {@link #setId(int)})
9645     * for its state to be saved.  This flag can only disable the
9646     * saving of this view; any child views may still have their state saved.
9647     *
9648     * @param enabled Set to false to <em>disable</em> state saving, or true
9649     * (the default) to allow it.
9650     *
9651     * @see #isSaveEnabled()
9652     * @see #setId(int)
9653     * @see #onSaveInstanceState()
9654     * @attr ref android.R.styleable#View_saveEnabled
9655     */
9656    public void setSaveEnabled(boolean enabled) {
9657        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
9658    }
9659
9660    /**
9661     * Gets whether the framework should discard touches when the view's
9662     * window is obscured by another visible window.
9663     * Refer to the {@link View} security documentation for more details.
9664     *
9665     * @return True if touch filtering is enabled.
9666     *
9667     * @see #setFilterTouchesWhenObscured(boolean)
9668     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9669     */
9670    @ViewDebug.ExportedProperty
9671    public boolean getFilterTouchesWhenObscured() {
9672        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
9673    }
9674
9675    /**
9676     * Sets whether the framework should discard touches when the view's
9677     * window is obscured by another visible window.
9678     * Refer to the {@link View} security documentation for more details.
9679     *
9680     * @param enabled True if touch filtering should be enabled.
9681     *
9682     * @see #getFilterTouchesWhenObscured
9683     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
9684     */
9685    public void setFilterTouchesWhenObscured(boolean enabled) {
9686        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
9687                FILTER_TOUCHES_WHEN_OBSCURED);
9688    }
9689
9690    /**
9691     * Indicates whether the entire hierarchy under this view will save its
9692     * state when a state saving traversal occurs from its parent.  The default
9693     * is true; if false, these views will not be saved unless
9694     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9695     *
9696     * @return Returns true if the view state saving from parent is enabled, else false.
9697     *
9698     * @see #setSaveFromParentEnabled(boolean)
9699     */
9700    public boolean isSaveFromParentEnabled() {
9701        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
9702    }
9703
9704    /**
9705     * Controls whether the entire hierarchy under this view will save its
9706     * state when a state saving traversal occurs from its parent.  The default
9707     * is true; if false, these views will not be saved unless
9708     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
9709     *
9710     * @param enabled Set to false to <em>disable</em> state saving, or true
9711     * (the default) to allow it.
9712     *
9713     * @see #isSaveFromParentEnabled()
9714     * @see #setId(int)
9715     * @see #onSaveInstanceState()
9716     */
9717    public void setSaveFromParentEnabled(boolean enabled) {
9718        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
9719    }
9720
9721
9722    /**
9723     * Returns whether this View is currently able to take focus.
9724     *
9725     * @return True if this view can take focus, or false otherwise.
9726     */
9727    @ViewDebug.ExportedProperty(category = "focus")
9728    public final boolean isFocusable() {
9729        return FOCUSABLE == (mViewFlags & FOCUSABLE);
9730    }
9731
9732    /**
9733     * Returns the focusable setting for this view.
9734     *
9735     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
9736     * @attr ref android.R.styleable#View_focusable
9737     */
9738    @ViewDebug.ExportedProperty(mapping = {
9739            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
9740            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
9741            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
9742            }, category = "focus")
9743    @Focusable
9744    public int getFocusable() {
9745        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
9746    }
9747
9748    /**
9749     * When a view is focusable, it may not want to take focus when in touch mode.
9750     * For example, a button would like focus when the user is navigating via a D-pad
9751     * so that the user can click on it, but once the user starts touching the screen,
9752     * the button shouldn't take focus
9753     * @return Whether the view is focusable in touch mode.
9754     * @attr ref android.R.styleable#View_focusableInTouchMode
9755     */
9756    @ViewDebug.ExportedProperty(category = "focus")
9757    public final boolean isFocusableInTouchMode() {
9758        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
9759    }
9760
9761    /**
9762     * Find the nearest view in the specified direction that can take focus.
9763     * This does not actually give focus to that view.
9764     *
9765     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
9766     *
9767     * @return The nearest focusable in the specified direction, or null if none
9768     *         can be found.
9769     */
9770    public View focusSearch(@FocusRealDirection int direction) {
9771        if (mParent != null) {
9772            return mParent.focusSearch(this, direction);
9773        } else {
9774            return null;
9775        }
9776    }
9777
9778    /**
9779     * Returns whether this View is a root of a keyboard navigation cluster.
9780     *
9781     * @return True if this view is a root of a cluster, or false otherwise.
9782     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9783     */
9784    @ViewDebug.ExportedProperty(category = "focus")
9785    public final boolean isKeyboardNavigationCluster() {
9786        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
9787    }
9788
9789    /**
9790     * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
9791     * will be ignored.
9792     *
9793     * @return the keyboard navigation cluster that this view is in (can be this view)
9794     *         or {@code null} if not in one
9795     */
9796    View findKeyboardNavigationCluster() {
9797        if (mParent instanceof View) {
9798            View cluster = ((View) mParent).findKeyboardNavigationCluster();
9799            if (cluster != null) {
9800                return cluster;
9801            } else if (isKeyboardNavigationCluster()) {
9802                return this;
9803            }
9804        }
9805        return null;
9806    }
9807
9808    /**
9809     * Set whether this view is a root of a keyboard navigation cluster.
9810     *
9811     * @param isCluster If true, this view is a root of a cluster.
9812     *
9813     * @attr ref android.R.styleable#View_keyboardNavigationCluster
9814     */
9815    public void setKeyboardNavigationCluster(boolean isCluster) {
9816        if (isCluster) {
9817            mPrivateFlags3 |= PFLAG3_CLUSTER;
9818        } else {
9819            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
9820        }
9821    }
9822
9823    /**
9824     * Sets this View as the one which receives focus the next time cluster navigation jumps
9825     * to the cluster containing this View. This does NOT change focus even if the cluster
9826     * containing this view is current.
9827     *
9828     * @hide
9829     */
9830    public final void setFocusedInCluster() {
9831        View top = findKeyboardNavigationCluster();
9832        if (top == this) {
9833            return;
9834        }
9835        ViewParent parent = mParent;
9836        View child = this;
9837        while (parent instanceof ViewGroup) {
9838            ((ViewGroup) parent).setFocusedInCluster(child);
9839            if (parent == top) {
9840                return;
9841            }
9842            child = (View) parent;
9843            parent = parent.getParent();
9844        }
9845    }
9846
9847    /**
9848     * Returns whether this View should receive focus when the focus is restored for the view
9849     * hierarchy containing this view.
9850     * <p>
9851     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9852     * window or serves as a target of cluster navigation.
9853     *
9854     * @see #restoreDefaultFocus()
9855     *
9856     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
9857     * @attr ref android.R.styleable#View_focusedByDefault
9858     */
9859    @ViewDebug.ExportedProperty(category = "focus")
9860    public final boolean isFocusedByDefault() {
9861        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
9862    }
9863
9864    /**
9865     * Sets whether this View should receive focus when the focus is restored for the view
9866     * hierarchy containing this view.
9867     * <p>
9868     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
9869     * window or serves as a target of cluster navigation.
9870     *
9871     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
9872     *                           {@code false} otherwise.
9873     *
9874     * @see #restoreDefaultFocus()
9875     *
9876     * @attr ref android.R.styleable#View_focusedByDefault
9877     */
9878    public void setFocusedByDefault(boolean isFocusedByDefault) {
9879        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
9880            return;
9881        }
9882
9883        if (isFocusedByDefault) {
9884            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
9885        } else {
9886            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
9887        }
9888
9889        if (mParent instanceof ViewGroup) {
9890            if (isFocusedByDefault) {
9891                ((ViewGroup) mParent).setDefaultFocus(this);
9892            } else {
9893                ((ViewGroup) mParent).clearDefaultFocus(this);
9894            }
9895        }
9896    }
9897
9898    /**
9899     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
9900     *
9901     * @return {@code true} if this view has default focus, {@code false} otherwise
9902     */
9903    boolean hasDefaultFocus() {
9904        return isFocusedByDefault();
9905    }
9906
9907    /**
9908     * Find the nearest keyboard navigation cluster in the specified direction.
9909     * This does not actually give focus to that cluster.
9910     *
9911     * @param currentCluster The starting point of the search. Null means the current cluster is not
9912     *                       found yet
9913     * @param direction Direction to look
9914     *
9915     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
9916     *         can be found
9917     */
9918    public View keyboardNavigationClusterSearch(View currentCluster,
9919            @FocusDirection int direction) {
9920        if (isKeyboardNavigationCluster()) {
9921            currentCluster = this;
9922        }
9923        if (isRootNamespace()) {
9924            // Root namespace means we should consider ourselves the top of the
9925            // tree for group searching; otherwise we could be group searching
9926            // into other tabs.  see LocalActivityManager and TabHost for more info.
9927            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
9928                    this, currentCluster, direction);
9929        } else if (mParent != null) {
9930            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
9931        }
9932        return null;
9933    }
9934
9935    /**
9936     * This method is the last chance for the focused view and its ancestors to
9937     * respond to an arrow key. This is called when the focused view did not
9938     * consume the key internally, nor could the view system find a new view in
9939     * the requested direction to give focus to.
9940     *
9941     * @param focused The currently focused view.
9942     * @param direction The direction focus wants to move. One of FOCUS_UP,
9943     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
9944     * @return True if the this view consumed this unhandled move.
9945     */
9946    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
9947        return false;
9948    }
9949
9950    /**
9951     * Sets whether this View should use a default focus highlight when it gets focused but doesn't
9952     * have {@link android.R.attr#state_focused} defined in its background.
9953     *
9954     * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
9955     *                                      highlight, {@code false} otherwise.
9956     *
9957     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
9958     */
9959    public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
9960        mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
9961    }
9962
9963    /**
9964
9965    /**
9966     * Returns whether this View should use a default focus highlight when it gets focused but
9967     * doesn't have {@link android.R.attr#state_focused} defined in its background.
9968     *
9969     * @return True if this View should use a default focus highlight.
9970     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
9971     */
9972    @ViewDebug.ExportedProperty(category = "focus")
9973    public final boolean getDefaultFocusHighlightEnabled() {
9974        return mDefaultFocusHighlightEnabled;
9975    }
9976
9977    /**
9978     * If a user manually specified the next view id for a particular direction,
9979     * use the root to look up the view.
9980     * @param root The root view of the hierarchy containing this view.
9981     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
9982     * or FOCUS_BACKWARD.
9983     * @return The user specified next view, or null if there is none.
9984     */
9985    View findUserSetNextFocus(View root, @FocusDirection int direction) {
9986        switch (direction) {
9987            case FOCUS_LEFT:
9988                if (mNextFocusLeftId == View.NO_ID) return null;
9989                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
9990            case FOCUS_RIGHT:
9991                if (mNextFocusRightId == View.NO_ID) return null;
9992                return findViewInsideOutShouldExist(root, mNextFocusRightId);
9993            case FOCUS_UP:
9994                if (mNextFocusUpId == View.NO_ID) return null;
9995                return findViewInsideOutShouldExist(root, mNextFocusUpId);
9996            case FOCUS_DOWN:
9997                if (mNextFocusDownId == View.NO_ID) return null;
9998                return findViewInsideOutShouldExist(root, mNextFocusDownId);
9999            case FOCUS_FORWARD:
10000                if (mNextFocusForwardId == View.NO_ID) return null;
10001                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
10002            case FOCUS_BACKWARD: {
10003                if (mID == View.NO_ID) return null;
10004                final int id = mID;
10005                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
10006                    @Override
10007                    public boolean test(View t) {
10008                        return t.mNextFocusForwardId == id;
10009                    }
10010                });
10011            }
10012        }
10013        return null;
10014    }
10015
10016    /**
10017     * If a user manually specified the next keyboard-navigation cluster for a particular direction,
10018     * use the root to look up the view.
10019     *
10020     * @param root the root view of the hierarchy containing this view
10021     * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
10022     * @return the user-specified next cluster, or {@code null} if there is none
10023     */
10024    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
10025        switch (direction) {
10026            case FOCUS_FORWARD:
10027                if (mNextClusterForwardId == View.NO_ID) return null;
10028                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
10029            case FOCUS_BACKWARD: {
10030                if (mID == View.NO_ID) return null;
10031                final int id = mID;
10032                return root.findViewByPredicateInsideOut(this,
10033                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
10034            }
10035        }
10036        return null;
10037    }
10038
10039    private View findViewInsideOutShouldExist(View root, int id) {
10040        if (mMatchIdPredicate == null) {
10041            mMatchIdPredicate = new MatchIdPredicate();
10042        }
10043        mMatchIdPredicate.mId = id;
10044        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
10045        if (result == null) {
10046            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
10047        }
10048        return result;
10049    }
10050
10051    /**
10052     * Find and return all focusable views that are descendants of this view,
10053     * possibly including this view if it is focusable itself.
10054     *
10055     * @param direction The direction of the focus
10056     * @return A list of focusable views
10057     */
10058    public ArrayList<View> getFocusables(@FocusDirection int direction) {
10059        ArrayList<View> result = new ArrayList<View>(24);
10060        addFocusables(result, direction);
10061        return result;
10062    }
10063
10064    /**
10065     * Add any focusable views that are descendants of this view (possibly
10066     * including this view if it is focusable itself) to views.  If we are in touch mode,
10067     * only add views that are also focusable in touch mode.
10068     *
10069     * @param views Focusable views found so far
10070     * @param direction The direction of the focus
10071     */
10072    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10073        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10074    }
10075
10076    /**
10077     * Adds any focusable views that are descendants of this view (possibly
10078     * including this view if it is focusable itself) to views. This method
10079     * adds all focusable views regardless if we are in touch mode or
10080     * only views focusable in touch mode if we are in touch mode or
10081     * only views that can take accessibility focus if accessibility is enabled
10082     * depending on the focusable mode parameter.
10083     *
10084     * @param views Focusable views found so far or null if all we are interested is
10085     *        the number of focusables.
10086     * @param direction The direction of the focus.
10087     * @param focusableMode The type of focusables to be added.
10088     *
10089     * @see #FOCUSABLES_ALL
10090     * @see #FOCUSABLES_TOUCH_MODE
10091     */
10092    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10093            @FocusableMode int focusableMode) {
10094        if (views == null) {
10095            return;
10096        }
10097        if (!isFocusable()) {
10098            return;
10099        }
10100        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10101                && !isFocusableInTouchMode()) {
10102            return;
10103        }
10104        views.add(this);
10105    }
10106
10107    /**
10108     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10109     * including this view if it is a cluster root itself) to views.
10110     *
10111     * @param views Keyboard navigation cluster roots found so far
10112     * @param direction Direction to look
10113     */
10114    public void addKeyboardNavigationClusters(
10115            @NonNull Collection<View> views,
10116            int direction) {
10117        if (!isKeyboardNavigationCluster()) {
10118            return;
10119        }
10120        if (!hasFocusable()) {
10121            return;
10122        }
10123        views.add(this);
10124    }
10125
10126    /**
10127     * Finds the Views that contain given text. The containment is case insensitive.
10128     * The search is performed by either the text that the View renders or the content
10129     * description that describes the view for accessibility purposes and the view does
10130     * not render or both. Clients can specify how the search is to be performed via
10131     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10132     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10133     *
10134     * @param outViews The output list of matching Views.
10135     * @param searched The text to match against.
10136     *
10137     * @see #FIND_VIEWS_WITH_TEXT
10138     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10139     * @see #setContentDescription(CharSequence)
10140     */
10141    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10142            @FindViewFlags int flags) {
10143        if (getAccessibilityNodeProvider() != null) {
10144            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10145                outViews.add(this);
10146            }
10147        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10148                && (searched != null && searched.length() > 0)
10149                && (mContentDescription != null && mContentDescription.length() > 0)) {
10150            String searchedLowerCase = searched.toString().toLowerCase();
10151            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10152            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10153                outViews.add(this);
10154            }
10155        }
10156    }
10157
10158    /**
10159     * Find and return all touchable views that are descendants of this view,
10160     * possibly including this view if it is touchable itself.
10161     *
10162     * @return A list of touchable views
10163     */
10164    public ArrayList<View> getTouchables() {
10165        ArrayList<View> result = new ArrayList<View>();
10166        addTouchables(result);
10167        return result;
10168    }
10169
10170    /**
10171     * Add any touchable views that are descendants of this view (possibly
10172     * including this view if it is touchable itself) to views.
10173     *
10174     * @param views Touchable views found so far
10175     */
10176    public void addTouchables(ArrayList<View> views) {
10177        final int viewFlags = mViewFlags;
10178
10179        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10180                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10181                && (viewFlags & ENABLED_MASK) == ENABLED) {
10182            views.add(this);
10183        }
10184    }
10185
10186    /**
10187     * Returns whether this View is accessibility focused.
10188     *
10189     * @return True if this View is accessibility focused.
10190     */
10191    public boolean isAccessibilityFocused() {
10192        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10193    }
10194
10195    /**
10196     * Call this to try to give accessibility focus to this view.
10197     *
10198     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10199     * returns false or the view is no visible or the view already has accessibility
10200     * focus.
10201     *
10202     * See also {@link #focusSearch(int)}, which is what you call to say that you
10203     * have focus, and you want your parent to look for the next one.
10204     *
10205     * @return Whether this view actually took accessibility focus.
10206     *
10207     * @hide
10208     */
10209    public boolean requestAccessibilityFocus() {
10210        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10211        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10212            return false;
10213        }
10214        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10215            return false;
10216        }
10217        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10218            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10219            ViewRootImpl viewRootImpl = getViewRootImpl();
10220            if (viewRootImpl != null) {
10221                viewRootImpl.setAccessibilityFocus(this, null);
10222            }
10223            invalidate();
10224            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10225            return true;
10226        }
10227        return false;
10228    }
10229
10230    /**
10231     * Call this to try to clear accessibility focus of this view.
10232     *
10233     * See also {@link #focusSearch(int)}, which is what you call to say that you
10234     * have focus, and you want your parent to look for the next one.
10235     *
10236     * @hide
10237     */
10238    public void clearAccessibilityFocus() {
10239        clearAccessibilityFocusNoCallbacks(0);
10240
10241        // Clear the global reference of accessibility focus if this view or
10242        // any of its descendants had accessibility focus. This will NOT send
10243        // an event or update internal state if focus is cleared from a
10244        // descendant view, which may leave views in inconsistent states.
10245        final ViewRootImpl viewRootImpl = getViewRootImpl();
10246        if (viewRootImpl != null) {
10247            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10248            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10249                viewRootImpl.setAccessibilityFocus(null, null);
10250            }
10251        }
10252    }
10253
10254    private void sendAccessibilityHoverEvent(int eventType) {
10255        // Since we are not delivering to a client accessibility events from not
10256        // important views (unless the clinet request that) we need to fire the
10257        // event from the deepest view exposed to the client. As a consequence if
10258        // the user crosses a not exposed view the client will see enter and exit
10259        // of the exposed predecessor followed by and enter and exit of that same
10260        // predecessor when entering and exiting the not exposed descendant. This
10261        // is fine since the client has a clear idea which view is hovered at the
10262        // price of a couple more events being sent. This is a simple and
10263        // working solution.
10264        View source = this;
10265        while (true) {
10266            if (source.includeForAccessibility()) {
10267                source.sendAccessibilityEvent(eventType);
10268                return;
10269            }
10270            ViewParent parent = source.getParent();
10271            if (parent instanceof View) {
10272                source = (View) parent;
10273            } else {
10274                return;
10275            }
10276        }
10277    }
10278
10279    /**
10280     * Clears accessibility focus without calling any callback methods
10281     * normally invoked in {@link #clearAccessibilityFocus()}. This method
10282     * is used separately from that one for clearing accessibility focus when
10283     * giving this focus to another view.
10284     *
10285     * @param action The action, if any, that led to focus being cleared. Set to
10286     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10287     * the window.
10288     */
10289    void clearAccessibilityFocusNoCallbacks(int action) {
10290        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10291            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10292            invalidate();
10293            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10294                AccessibilityEvent event = AccessibilityEvent.obtain(
10295                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10296                event.setAction(action);
10297                if (mAccessibilityDelegate != null) {
10298                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10299                } else {
10300                    sendAccessibilityEventUnchecked(event);
10301                }
10302            }
10303        }
10304    }
10305
10306    /**
10307     * Call this to try to give focus to a specific view or to one of its
10308     * descendants.
10309     *
10310     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10311     * false), or if it is focusable and it is not focusable in touch mode
10312     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10313     *
10314     * See also {@link #focusSearch(int)}, which is what you call to say that you
10315     * have focus, and you want your parent to look for the next one.
10316     *
10317     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10318     * {@link #FOCUS_DOWN} and <code>null</code>.
10319     *
10320     * @return Whether this view or one of its descendants actually took focus.
10321     */
10322    public final boolean requestFocus() {
10323        return requestFocus(View.FOCUS_DOWN);
10324    }
10325
10326    /**
10327     * This will request focus for whichever View was last focused within this
10328     * cluster before a focus-jump out of it.
10329     *
10330     * @hide
10331     */
10332    @TestApi
10333    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10334        // Prioritize focusableByDefault over algorithmic focus selection.
10335        if (restoreDefaultFocus()) {
10336            return true;
10337        }
10338        return requestFocus(direction);
10339    }
10340
10341    /**
10342     * This will request focus for whichever View not in a cluster was last focused before a
10343     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10344     * the "first" focusable view it finds.
10345     *
10346     * @hide
10347     */
10348    @TestApi
10349    public boolean restoreFocusNotInCluster() {
10350        return requestFocus(View.FOCUS_DOWN);
10351    }
10352
10353    /**
10354     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10355     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10356     *
10357     * @return Whether this view or one of its descendants actually took focus
10358     */
10359    public boolean restoreDefaultFocus() {
10360        return requestFocus(View.FOCUS_DOWN);
10361    }
10362
10363    /**
10364     * Call this to try to give focus to a specific view or to one of its
10365     * descendants and give it a hint about what direction focus is heading.
10366     *
10367     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10368     * false), or if it is focusable and it is not focusable in touch mode
10369     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10370     *
10371     * See also {@link #focusSearch(int)}, which is what you call to say that you
10372     * have focus, and you want your parent to look for the next one.
10373     *
10374     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10375     * <code>null</code> set for the previously focused rectangle.
10376     *
10377     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10378     * @return Whether this view or one of its descendants actually took focus.
10379     */
10380    public final boolean requestFocus(int direction) {
10381        return requestFocus(direction, null);
10382    }
10383
10384    /**
10385     * Call this to try to give focus to a specific view or to one of its descendants
10386     * and give it hints about the direction and a specific rectangle that the focus
10387     * is coming from.  The rectangle can help give larger views a finer grained hint
10388     * about where focus is coming from, and therefore, where to show selection, or
10389     * forward focus change internally.
10390     *
10391     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10392     * false), or if it is focusable and it is not focusable in touch mode
10393     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10394     *
10395     * A View will not take focus if it is not visible.
10396     *
10397     * A View will not take focus if one of its parents has
10398     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10399     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10400     *
10401     * See also {@link #focusSearch(int)}, which is what you call to say that you
10402     * have focus, and you want your parent to look for the next one.
10403     *
10404     * You may wish to override this method if your custom {@link View} has an internal
10405     * {@link View} that it wishes to forward the request to.
10406     *
10407     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10408     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10409     *        to give a finer grained hint about where focus is coming from.  May be null
10410     *        if there is no hint.
10411     * @return Whether this view or one of its descendants actually took focus.
10412     */
10413    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10414        return requestFocusNoSearch(direction, previouslyFocusedRect);
10415    }
10416
10417    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10418        // need to be focusable
10419        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10420                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10421            return false;
10422        }
10423
10424        // need to be focusable in touch mode if in touch mode
10425        if (isInTouchMode() &&
10426            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10427               return false;
10428        }
10429
10430        // need to not have any parents blocking us
10431        if (hasAncestorThatBlocksDescendantFocus()) {
10432            return false;
10433        }
10434
10435        handleFocusGainInternal(direction, previouslyFocusedRect);
10436        return true;
10437    }
10438
10439    /**
10440     * Call this to try to give focus to a specific view or to one of its descendants. This is a
10441     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10442     * touch mode to request focus when they are touched.
10443     *
10444     * @return Whether this view or one of its descendants actually took focus.
10445     *
10446     * @see #isInTouchMode()
10447     *
10448     */
10449    public final boolean requestFocusFromTouch() {
10450        // Leave touch mode if we need to
10451        if (isInTouchMode()) {
10452            ViewRootImpl viewRoot = getViewRootImpl();
10453            if (viewRoot != null) {
10454                viewRoot.ensureTouchMode(false);
10455            }
10456        }
10457        return requestFocus(View.FOCUS_DOWN);
10458    }
10459
10460    /**
10461     * @return Whether any ancestor of this view blocks descendant focus.
10462     */
10463    private boolean hasAncestorThatBlocksDescendantFocus() {
10464        final boolean focusableInTouchMode = isFocusableInTouchMode();
10465        ViewParent ancestor = mParent;
10466        while (ancestor instanceof ViewGroup) {
10467            final ViewGroup vgAncestor = (ViewGroup) ancestor;
10468            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10469                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10470                return true;
10471            } else {
10472                ancestor = vgAncestor.getParent();
10473            }
10474        }
10475        return false;
10476    }
10477
10478    /**
10479     * Gets the mode for determining whether this View is important for accessibility.
10480     * A view is important for accessibility if it fires accessibility events and if it
10481     * is reported to accessibility services that query the screen.
10482     *
10483     * @return The mode for determining whether a view is important for accessibility, one
10484     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10485     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10486     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10487     *
10488     * @attr ref android.R.styleable#View_importantForAccessibility
10489     *
10490     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10491     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10492     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10493     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10494     */
10495    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10496            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10497            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10498            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10499            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10500                    to = "noHideDescendants")
10501        })
10502    public int getImportantForAccessibility() {
10503        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10504                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10505    }
10506
10507    /**
10508     * Sets the live region mode for this view. This indicates to accessibility
10509     * services whether they should automatically notify the user about changes
10510     * to the view's content description or text, or to the content descriptions
10511     * or text of the view's children (where applicable).
10512     * <p>
10513     * For example, in a login screen with a TextView that displays an "incorrect
10514     * password" notification, that view should be marked as a live region with
10515     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10516     * <p>
10517     * To disable change notifications for this view, use
10518     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10519     * mode for most views.
10520     * <p>
10521     * To indicate that the user should be notified of changes, use
10522     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10523     * <p>
10524     * If the view's changes should interrupt ongoing speech and notify the user
10525     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10526     *
10527     * @param mode The live region mode for this view, one of:
10528     *        <ul>
10529     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10530     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10531     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10532     *        </ul>
10533     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10534     */
10535    public void setAccessibilityLiveRegion(int mode) {
10536        if (mode != getAccessibilityLiveRegion()) {
10537            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10538            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10539                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10540            notifyViewAccessibilityStateChangedIfNeeded(
10541                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10542        }
10543    }
10544
10545    /**
10546     * Gets the live region mode for this View.
10547     *
10548     * @return The live region mode for the view.
10549     *
10550     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10551     *
10552     * @see #setAccessibilityLiveRegion(int)
10553     */
10554    public int getAccessibilityLiveRegion() {
10555        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10556                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10557    }
10558
10559    /**
10560     * Sets how to determine whether this view is important for accessibility
10561     * which is if it fires accessibility events and if it is reported to
10562     * accessibility services that query the screen.
10563     *
10564     * @param mode How to determine whether this view is important for accessibility.
10565     *
10566     * @attr ref android.R.styleable#View_importantForAccessibility
10567     *
10568     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10569     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10570     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10571     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10572     */
10573    public void setImportantForAccessibility(int mode) {
10574        final int oldMode = getImportantForAccessibility();
10575        if (mode != oldMode) {
10576            final boolean hideDescendants =
10577                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
10578
10579            // If this node or its descendants are no longer important, try to
10580            // clear accessibility focus.
10581            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
10582                final View focusHost = findAccessibilityFocusHost(hideDescendants);
10583                if (focusHost != null) {
10584                    focusHost.clearAccessibilityFocus();
10585                }
10586            }
10587
10588            // If we're moving between AUTO and another state, we might not need
10589            // to send a subtree changed notification. We'll store the computed
10590            // importance, since we'll need to check it later to make sure.
10591            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
10592                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
10593            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
10594            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10595            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
10596                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10597            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
10598                notifySubtreeAccessibilityStateChangedIfNeeded();
10599            } else {
10600                notifyViewAccessibilityStateChangedIfNeeded(
10601                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10602            }
10603        }
10604    }
10605
10606    /**
10607     * Returns the view within this view's hierarchy that is hosting
10608     * accessibility focus.
10609     *
10610     * @param searchDescendants whether to search for focus in descendant views
10611     * @return the view hosting accessibility focus, or {@code null}
10612     */
10613    private View findAccessibilityFocusHost(boolean searchDescendants) {
10614        if (isAccessibilityFocusedViewOrHost()) {
10615            return this;
10616        }
10617
10618        if (searchDescendants) {
10619            final ViewRootImpl viewRoot = getViewRootImpl();
10620            if (viewRoot != null) {
10621                final View focusHost = viewRoot.getAccessibilityFocusedHost();
10622                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10623                    return focusHost;
10624                }
10625            }
10626        }
10627
10628        return null;
10629    }
10630
10631    /**
10632     * Computes whether this view should be exposed for accessibility. In
10633     * general, views that are interactive or provide information are exposed
10634     * while views that serve only as containers are hidden.
10635     * <p>
10636     * If an ancestor of this view has importance
10637     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
10638     * returns <code>false</code>.
10639     * <p>
10640     * Otherwise, the value is computed according to the view's
10641     * {@link #getImportantForAccessibility()} value:
10642     * <ol>
10643     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
10644     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
10645     * </code>
10646     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
10647     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
10648     * view satisfies any of the following:
10649     * <ul>
10650     * <li>Is actionable, e.g. {@link #isClickable()},
10651     * {@link #isLongClickable()}, or {@link #isFocusable()}
10652     * <li>Has an {@link AccessibilityDelegate}
10653     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
10654     * {@link OnKeyListener}, etc.
10655     * <li>Is an accessibility live region, e.g.
10656     * {@link #getAccessibilityLiveRegion()} is not
10657     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
10658     * </ul>
10659     * </ol>
10660     *
10661     * @return Whether the view is exposed for accessibility.
10662     * @see #setImportantForAccessibility(int)
10663     * @see #getImportantForAccessibility()
10664     */
10665    public boolean isImportantForAccessibility() {
10666        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10667                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10668        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
10669                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10670            return false;
10671        }
10672
10673        // Check parent mode to ensure we're not hidden.
10674        ViewParent parent = mParent;
10675        while (parent instanceof View) {
10676            if (((View) parent).getImportantForAccessibility()
10677                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
10678                return false;
10679            }
10680            parent = parent.getParent();
10681        }
10682
10683        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
10684                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
10685                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
10686    }
10687
10688    /**
10689     * Gets the parent for accessibility purposes. Note that the parent for
10690     * accessibility is not necessary the immediate parent. It is the first
10691     * predecessor that is important for accessibility.
10692     *
10693     * @return The parent for accessibility purposes.
10694     */
10695    public ViewParent getParentForAccessibility() {
10696        if (mParent instanceof View) {
10697            View parentView = (View) mParent;
10698            if (parentView.includeForAccessibility()) {
10699                return mParent;
10700            } else {
10701                return mParent.getParentForAccessibility();
10702            }
10703        }
10704        return null;
10705    }
10706
10707    /**
10708     * Adds the children of this View relevant for accessibility to the given list
10709     * as output. Since some Views are not important for accessibility the added
10710     * child views are not necessarily direct children of this view, rather they are
10711     * the first level of descendants important for accessibility.
10712     *
10713     * @param outChildren The output list that will receive children for accessibility.
10714     */
10715    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
10716
10717    }
10718
10719    /**
10720     * Whether to regard this view for accessibility. A view is regarded for
10721     * accessibility if it is important for accessibility or the querying
10722     * accessibility service has explicitly requested that view not
10723     * important for accessibility are regarded.
10724     *
10725     * @return Whether to regard the view for accessibility.
10726     *
10727     * @hide
10728     */
10729    public boolean includeForAccessibility() {
10730        if (mAttachInfo != null) {
10731            return (mAttachInfo.mAccessibilityFetchFlags
10732                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
10733                    || isImportantForAccessibility();
10734        }
10735        return false;
10736    }
10737
10738    /**
10739     * Returns whether the View is considered actionable from
10740     * accessibility perspective. Such view are important for
10741     * accessibility.
10742     *
10743     * @return True if the view is actionable for accessibility.
10744     *
10745     * @hide
10746     */
10747    public boolean isActionableForAccessibility() {
10748        return (isClickable() || isLongClickable() || isFocusable());
10749    }
10750
10751    /**
10752     * Returns whether the View has registered callbacks which makes it
10753     * important for accessibility.
10754     *
10755     * @return True if the view is actionable for accessibility.
10756     */
10757    private boolean hasListenersForAccessibility() {
10758        ListenerInfo info = getListenerInfo();
10759        return mTouchDelegate != null || info.mOnKeyListener != null
10760                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
10761                || info.mOnHoverListener != null || info.mOnDragListener != null;
10762    }
10763
10764    /**
10765     * Notifies that the accessibility state of this view changed. The change
10766     * is local to this view and does not represent structural changes such
10767     * as children and parent. For example, the view became focusable. The
10768     * notification is at at most once every
10769     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10770     * to avoid unnecessary load to the system. Also once a view has a pending
10771     * notification this method is a NOP until the notification has been sent.
10772     *
10773     * @hide
10774     */
10775    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
10776        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10777            return;
10778        }
10779        if (mSendViewStateChangedAccessibilityEvent == null) {
10780            mSendViewStateChangedAccessibilityEvent =
10781                    new SendViewStateChangedAccessibilityEvent();
10782        }
10783        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
10784    }
10785
10786    /**
10787     * Notifies that the accessibility state of this view changed. The change
10788     * is *not* local to this view and does represent structural changes such
10789     * as children and parent. For example, the view size changed. The
10790     * notification is at at most once every
10791     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
10792     * to avoid unnecessary load to the system. Also once a view has a pending
10793     * notification this method is a NOP until the notification has been sent.
10794     *
10795     * @hide
10796     */
10797    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
10798        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
10799            return;
10800        }
10801        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
10802            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10803            if (mParent != null) {
10804                try {
10805                    mParent.notifySubtreeAccessibilityStateChanged(
10806                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
10807                } catch (AbstractMethodError e) {
10808                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
10809                            " does not fully implement ViewParent", e);
10810                }
10811            }
10812        }
10813    }
10814
10815    /**
10816     * Change the visibility of the View without triggering any other changes. This is
10817     * important for transitions, where visibility changes should not adjust focus or
10818     * trigger a new layout. This is only used when the visibility has already been changed
10819     * and we need a transient value during an animation. When the animation completes,
10820     * the original visibility value is always restored.
10821     *
10822     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
10823     * @hide
10824     */
10825    public void setTransitionVisibility(@Visibility int visibility) {
10826        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
10827    }
10828
10829    /**
10830     * Reset the flag indicating the accessibility state of the subtree rooted
10831     * at this view changed.
10832     */
10833    void resetSubtreeAccessibilityStateChanged() {
10834        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
10835    }
10836
10837    /**
10838     * Report an accessibility action to this view's parents for delegated processing.
10839     *
10840     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
10841     * call this method to delegate an accessibility action to a supporting parent. If the parent
10842     * returns true from its
10843     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
10844     * method this method will return true to signify that the action was consumed.</p>
10845     *
10846     * <p>This method is useful for implementing nested scrolling child views. If
10847     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
10848     * a custom view implementation may invoke this method to allow a parent to consume the
10849     * scroll first. If this method returns true the custom view should skip its own scrolling
10850     * behavior.</p>
10851     *
10852     * @param action Accessibility action to delegate
10853     * @param arguments Optional action arguments
10854     * @return true if the action was consumed by a parent
10855     */
10856    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
10857        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
10858            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
10859                return true;
10860            }
10861        }
10862        return false;
10863    }
10864
10865    /**
10866     * Performs the specified accessibility action on the view. For
10867     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
10868     * <p>
10869     * If an {@link AccessibilityDelegate} has been specified via calling
10870     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
10871     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
10872     * is responsible for handling this call.
10873     * </p>
10874     *
10875     * <p>The default implementation will delegate
10876     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
10877     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
10878     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
10879     *
10880     * @param action The action to perform.
10881     * @param arguments Optional action arguments.
10882     * @return Whether the action was performed.
10883     */
10884    public boolean performAccessibilityAction(int action, Bundle arguments) {
10885      if (mAccessibilityDelegate != null) {
10886          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
10887      } else {
10888          return performAccessibilityActionInternal(action, arguments);
10889      }
10890    }
10891
10892   /**
10893    * @see #performAccessibilityAction(int, Bundle)
10894    *
10895    * Note: Called from the default {@link AccessibilityDelegate}.
10896    *
10897    * @hide
10898    */
10899    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
10900        if (isNestedScrollingEnabled()
10901                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
10902                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
10903                || action == R.id.accessibilityActionScrollUp
10904                || action == R.id.accessibilityActionScrollLeft
10905                || action == R.id.accessibilityActionScrollDown
10906                || action == R.id.accessibilityActionScrollRight)) {
10907            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
10908                return true;
10909            }
10910        }
10911
10912        switch (action) {
10913            case AccessibilityNodeInfo.ACTION_CLICK: {
10914                if (isClickable()) {
10915                    performClick();
10916                    return true;
10917                }
10918            } break;
10919            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
10920                if (isLongClickable()) {
10921                    performLongClick();
10922                    return true;
10923                }
10924            } break;
10925            case AccessibilityNodeInfo.ACTION_FOCUS: {
10926                if (!hasFocus()) {
10927                    // Get out of touch mode since accessibility
10928                    // wants to move focus around.
10929                    getViewRootImpl().ensureTouchMode(false);
10930                    return requestFocus();
10931                }
10932            } break;
10933            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
10934                if (hasFocus()) {
10935                    clearFocus();
10936                    return !isFocused();
10937                }
10938            } break;
10939            case AccessibilityNodeInfo.ACTION_SELECT: {
10940                if (!isSelected()) {
10941                    setSelected(true);
10942                    return isSelected();
10943                }
10944            } break;
10945            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
10946                if (isSelected()) {
10947                    setSelected(false);
10948                    return !isSelected();
10949                }
10950            } break;
10951            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
10952                if (!isAccessibilityFocused()) {
10953                    return requestAccessibilityFocus();
10954                }
10955            } break;
10956            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
10957                if (isAccessibilityFocused()) {
10958                    clearAccessibilityFocus();
10959                    return true;
10960                }
10961            } break;
10962            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
10963                if (arguments != null) {
10964                    final int granularity = arguments.getInt(
10965                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10966                    final boolean extendSelection = arguments.getBoolean(
10967                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10968                    return traverseAtGranularity(granularity, true, extendSelection);
10969                }
10970            } break;
10971            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
10972                if (arguments != null) {
10973                    final int granularity = arguments.getInt(
10974                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
10975                    final boolean extendSelection = arguments.getBoolean(
10976                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
10977                    return traverseAtGranularity(granularity, false, extendSelection);
10978                }
10979            } break;
10980            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
10981                CharSequence text = getIterableTextForAccessibility();
10982                if (text == null) {
10983                    return false;
10984                }
10985                final int start = (arguments != null) ? arguments.getInt(
10986                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
10987                final int end = (arguments != null) ? arguments.getInt(
10988                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
10989                // Only cursor position can be specified (selection length == 0)
10990                if ((getAccessibilitySelectionStart() != start
10991                        || getAccessibilitySelectionEnd() != end)
10992                        && (start == end)) {
10993                    setAccessibilitySelection(start, end);
10994                    notifyViewAccessibilityStateChangedIfNeeded(
10995                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10996                    return true;
10997                }
10998            } break;
10999            case R.id.accessibilityActionShowOnScreen: {
11000                if (mAttachInfo != null) {
11001                    final Rect r = mAttachInfo.mTmpInvalRect;
11002                    getDrawingRect(r);
11003                    return requestRectangleOnScreen(r, true);
11004                }
11005            } break;
11006            case R.id.accessibilityActionContextClick: {
11007                if (isContextClickable()) {
11008                    performContextClick();
11009                    return true;
11010                }
11011            } break;
11012        }
11013        return false;
11014    }
11015
11016    private boolean traverseAtGranularity(int granularity, boolean forward,
11017            boolean extendSelection) {
11018        CharSequence text = getIterableTextForAccessibility();
11019        if (text == null || text.length() == 0) {
11020            return false;
11021        }
11022        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
11023        if (iterator == null) {
11024            return false;
11025        }
11026        int current = getAccessibilitySelectionEnd();
11027        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11028            current = forward ? 0 : text.length();
11029        }
11030        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
11031        if (range == null) {
11032            return false;
11033        }
11034        final int segmentStart = range[0];
11035        final int segmentEnd = range[1];
11036        int selectionStart;
11037        int selectionEnd;
11038        if (extendSelection && isAccessibilitySelectionExtendable()) {
11039            selectionStart = getAccessibilitySelectionStart();
11040            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11041                selectionStart = forward ? segmentStart : segmentEnd;
11042            }
11043            selectionEnd = forward ? segmentEnd : segmentStart;
11044        } else {
11045            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
11046        }
11047        setAccessibilitySelection(selectionStart, selectionEnd);
11048        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
11049                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
11050        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
11051        return true;
11052    }
11053
11054    /**
11055     * Gets the text reported for accessibility purposes.
11056     *
11057     * @return The accessibility text.
11058     *
11059     * @hide
11060     */
11061    public CharSequence getIterableTextForAccessibility() {
11062        return getContentDescription();
11063    }
11064
11065    /**
11066     * Gets whether accessibility selection can be extended.
11067     *
11068     * @return If selection is extensible.
11069     *
11070     * @hide
11071     */
11072    public boolean isAccessibilitySelectionExtendable() {
11073        return false;
11074    }
11075
11076    /**
11077     * @hide
11078     */
11079    public int getAccessibilitySelectionStart() {
11080        return mAccessibilityCursorPosition;
11081    }
11082
11083    /**
11084     * @hide
11085     */
11086    public int getAccessibilitySelectionEnd() {
11087        return getAccessibilitySelectionStart();
11088    }
11089
11090    /**
11091     * @hide
11092     */
11093    public void setAccessibilitySelection(int start, int end) {
11094        if (start ==  end && end == mAccessibilityCursorPosition) {
11095            return;
11096        }
11097        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11098            mAccessibilityCursorPosition = start;
11099        } else {
11100            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11101        }
11102        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11103    }
11104
11105    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11106            int fromIndex, int toIndex) {
11107        if (mParent == null) {
11108            return;
11109        }
11110        AccessibilityEvent event = AccessibilityEvent.obtain(
11111                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11112        onInitializeAccessibilityEvent(event);
11113        onPopulateAccessibilityEvent(event);
11114        event.setFromIndex(fromIndex);
11115        event.setToIndex(toIndex);
11116        event.setAction(action);
11117        event.setMovementGranularity(granularity);
11118        mParent.requestSendAccessibilityEvent(this, event);
11119    }
11120
11121    /**
11122     * @hide
11123     */
11124    public TextSegmentIterator getIteratorForGranularity(int granularity) {
11125        switch (granularity) {
11126            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11127                CharSequence text = getIterableTextForAccessibility();
11128                if (text != null && text.length() > 0) {
11129                    CharacterTextSegmentIterator iterator =
11130                        CharacterTextSegmentIterator.getInstance(
11131                                mContext.getResources().getConfiguration().locale);
11132                    iterator.initialize(text.toString());
11133                    return iterator;
11134                }
11135            } break;
11136            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11137                CharSequence text = getIterableTextForAccessibility();
11138                if (text != null && text.length() > 0) {
11139                    WordTextSegmentIterator iterator =
11140                        WordTextSegmentIterator.getInstance(
11141                                mContext.getResources().getConfiguration().locale);
11142                    iterator.initialize(text.toString());
11143                    return iterator;
11144                }
11145            } break;
11146            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11147                CharSequence text = getIterableTextForAccessibility();
11148                if (text != null && text.length() > 0) {
11149                    ParagraphTextSegmentIterator iterator =
11150                        ParagraphTextSegmentIterator.getInstance();
11151                    iterator.initialize(text.toString());
11152                    return iterator;
11153                }
11154            } break;
11155        }
11156        return null;
11157    }
11158
11159    /**
11160     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11161     * and {@link #onFinishTemporaryDetach()}.
11162     *
11163     * <p>This method always returns {@code true} when called directly or indirectly from
11164     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11165     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11166     * <ul>
11167     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11168     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11169     * </ul>
11170     * </p>
11171     *
11172     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11173     * and {@link #onFinishTemporaryDetach()}.
11174     */
11175    public final boolean isTemporarilyDetached() {
11176        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11177    }
11178
11179    /**
11180     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11181     * a container View.
11182     */
11183    @CallSuper
11184    public void dispatchStartTemporaryDetach() {
11185        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11186        notifyEnterOrExitForAutoFillIfNeeded(false);
11187        onStartTemporaryDetach();
11188    }
11189
11190    /**
11191     * This is called when a container is going to temporarily detach a child, with
11192     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11193     * It will either be followed by {@link #onFinishTemporaryDetach()} or
11194     * {@link #onDetachedFromWindow()} when the container is done.
11195     */
11196    public void onStartTemporaryDetach() {
11197        removeUnsetPressCallback();
11198        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11199    }
11200
11201    /**
11202     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11203     * a container View.
11204     */
11205    @CallSuper
11206    public void dispatchFinishTemporaryDetach() {
11207        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11208        onFinishTemporaryDetach();
11209        if (hasWindowFocus() && hasFocus()) {
11210            InputMethodManager.getInstance().focusIn(this);
11211        }
11212        notifyEnterOrExitForAutoFillIfNeeded(true);
11213    }
11214
11215    /**
11216     * Called after {@link #onStartTemporaryDetach} when the container is done
11217     * changing the view.
11218     */
11219    public void onFinishTemporaryDetach() {
11220    }
11221
11222    /**
11223     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11224     * for this view's window.  Returns null if the view is not currently attached
11225     * to the window.  Normally you will not need to use this directly, but
11226     * just use the standard high-level event callbacks like
11227     * {@link #onKeyDown(int, KeyEvent)}.
11228     */
11229    public KeyEvent.DispatcherState getKeyDispatcherState() {
11230        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11231    }
11232
11233    /**
11234     * Dispatch a key event before it is processed by any input method
11235     * associated with the view hierarchy.  This can be used to intercept
11236     * key events in special situations before the IME consumes them; a
11237     * typical example would be handling the BACK key to update the application's
11238     * UI instead of allowing the IME to see it and close itself.
11239     *
11240     * @param event The key event to be dispatched.
11241     * @return True if the event was handled, false otherwise.
11242     */
11243    public boolean dispatchKeyEventPreIme(KeyEvent event) {
11244        return onKeyPreIme(event.getKeyCode(), event);
11245    }
11246
11247    /**
11248     * Dispatch a key event to the next view on the focus path. This path runs
11249     * from the top of the view tree down to the currently focused view. If this
11250     * view has focus, it will dispatch to itself. Otherwise it will dispatch
11251     * the next node down the focus path. This method also fires any key
11252     * listeners.
11253     *
11254     * @param event The key event to be dispatched.
11255     * @return True if the event was handled, false otherwise.
11256     */
11257    public boolean dispatchKeyEvent(KeyEvent event) {
11258        if (mInputEventConsistencyVerifier != null) {
11259            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11260        }
11261
11262        // Give any attached key listener a first crack at the event.
11263        //noinspection SimplifiableIfStatement
11264        ListenerInfo li = mListenerInfo;
11265        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11266                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11267            return true;
11268        }
11269
11270        if (event.dispatch(this, mAttachInfo != null
11271                ? mAttachInfo.mKeyDispatchState : null, this)) {
11272            return true;
11273        }
11274
11275        if (mInputEventConsistencyVerifier != null) {
11276            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11277        }
11278        return false;
11279    }
11280
11281    /**
11282     * Dispatches a key shortcut event.
11283     *
11284     * @param event The key event to be dispatched.
11285     * @return True if the event was handled by the view, false otherwise.
11286     */
11287    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11288        return onKeyShortcut(event.getKeyCode(), event);
11289    }
11290
11291    /**
11292     * Pass the touch screen motion event down to the target view, or this
11293     * view if it is the target.
11294     *
11295     * @param event The motion event to be dispatched.
11296     * @return True if the event was handled by the view, false otherwise.
11297     */
11298    public boolean dispatchTouchEvent(MotionEvent event) {
11299        // If the event should be handled by accessibility focus first.
11300        if (event.isTargetAccessibilityFocus()) {
11301            // We don't have focus or no virtual descendant has it, do not handle the event.
11302            if (!isAccessibilityFocusedViewOrHost()) {
11303                return false;
11304            }
11305            // We have focus and got the event, then use normal event dispatch.
11306            event.setTargetAccessibilityFocus(false);
11307        }
11308
11309        boolean result = false;
11310
11311        if (mInputEventConsistencyVerifier != null) {
11312            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11313        }
11314
11315        final int actionMasked = event.getActionMasked();
11316        if (actionMasked == MotionEvent.ACTION_DOWN) {
11317            // Defensive cleanup for new gesture
11318            stopNestedScroll();
11319        }
11320
11321        if (onFilterTouchEventForSecurity(event)) {
11322            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11323                result = true;
11324            }
11325            //noinspection SimplifiableIfStatement
11326            ListenerInfo li = mListenerInfo;
11327            if (li != null && li.mOnTouchListener != null
11328                    && (mViewFlags & ENABLED_MASK) == ENABLED
11329                    && li.mOnTouchListener.onTouch(this, event)) {
11330                result = true;
11331            }
11332
11333            if (!result && onTouchEvent(event)) {
11334                result = true;
11335            }
11336        }
11337
11338        if (!result && mInputEventConsistencyVerifier != null) {
11339            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11340        }
11341
11342        // Clean up after nested scrolls if this is the end of a gesture;
11343        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11344        // of the gesture.
11345        if (actionMasked == MotionEvent.ACTION_UP ||
11346                actionMasked == MotionEvent.ACTION_CANCEL ||
11347                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11348            stopNestedScroll();
11349        }
11350
11351        return result;
11352    }
11353
11354    boolean isAccessibilityFocusedViewOrHost() {
11355        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11356                .getAccessibilityFocusedHost() == this);
11357    }
11358
11359    /**
11360     * Filter the touch event to apply security policies.
11361     *
11362     * @param event The motion event to be filtered.
11363     * @return True if the event should be dispatched, false if the event should be dropped.
11364     *
11365     * @see #getFilterTouchesWhenObscured
11366     */
11367    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11368        //noinspection RedundantIfStatement
11369        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11370                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11371            // Window is obscured, drop this touch.
11372            return false;
11373        }
11374        return true;
11375    }
11376
11377    /**
11378     * Pass a trackball motion event down to the focused view.
11379     *
11380     * @param event The motion event to be dispatched.
11381     * @return True if the event was handled by the view, false otherwise.
11382     */
11383    public boolean dispatchTrackballEvent(MotionEvent event) {
11384        if (mInputEventConsistencyVerifier != null) {
11385            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11386        }
11387
11388        return onTrackballEvent(event);
11389    }
11390
11391    /**
11392     * Pass a captured pointer event down to the focused view.
11393     *
11394     * @param event The motion event to be dispatched.
11395     * @return True if the event was handled by the view, false otherwise.
11396     */
11397    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11398        if (!hasPointerCapture()) {
11399            return false;
11400        }
11401        //noinspection SimplifiableIfStatement
11402        ListenerInfo li = mListenerInfo;
11403        if (li != null && li.mOnCapturedPointerListener != null
11404                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11405            return true;
11406        }
11407        return onCapturedPointerEvent(event);
11408    }
11409
11410    /**
11411     * Dispatch a generic motion event.
11412     * <p>
11413     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11414     * are delivered to the view under the pointer.  All other generic motion events are
11415     * delivered to the focused view.  Hover events are handled specially and are delivered
11416     * to {@link #onHoverEvent(MotionEvent)}.
11417     * </p>
11418     *
11419     * @param event The motion event to be dispatched.
11420     * @return True if the event was handled by the view, false otherwise.
11421     */
11422    public boolean dispatchGenericMotionEvent(MotionEvent event) {
11423        if (mInputEventConsistencyVerifier != null) {
11424            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11425        }
11426
11427        final int source = event.getSource();
11428        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11429            final int action = event.getAction();
11430            if (action == MotionEvent.ACTION_HOVER_ENTER
11431                    || action == MotionEvent.ACTION_HOVER_MOVE
11432                    || action == MotionEvent.ACTION_HOVER_EXIT) {
11433                if (dispatchHoverEvent(event)) {
11434                    return true;
11435                }
11436            } else if (dispatchGenericPointerEvent(event)) {
11437                return true;
11438            }
11439        } else if (dispatchGenericFocusedEvent(event)) {
11440            return true;
11441        }
11442
11443        if (dispatchGenericMotionEventInternal(event)) {
11444            return true;
11445        }
11446
11447        if (mInputEventConsistencyVerifier != null) {
11448            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11449        }
11450        return false;
11451    }
11452
11453    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11454        //noinspection SimplifiableIfStatement
11455        ListenerInfo li = mListenerInfo;
11456        if (li != null && li.mOnGenericMotionListener != null
11457                && (mViewFlags & ENABLED_MASK) == ENABLED
11458                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11459            return true;
11460        }
11461
11462        if (onGenericMotionEvent(event)) {
11463            return true;
11464        }
11465
11466        final int actionButton = event.getActionButton();
11467        switch (event.getActionMasked()) {
11468            case MotionEvent.ACTION_BUTTON_PRESS:
11469                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11470                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11471                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11472                    if (performContextClick(event.getX(), event.getY())) {
11473                        mInContextButtonPress = true;
11474                        setPressed(true, event.getX(), event.getY());
11475                        removeTapCallback();
11476                        removeLongPressCallback();
11477                        return true;
11478                    }
11479                }
11480                break;
11481
11482            case MotionEvent.ACTION_BUTTON_RELEASE:
11483                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11484                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11485                    mInContextButtonPress = false;
11486                    mIgnoreNextUpEvent = true;
11487                }
11488                break;
11489        }
11490
11491        if (mInputEventConsistencyVerifier != null) {
11492            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11493        }
11494        return false;
11495    }
11496
11497    /**
11498     * Dispatch a hover event.
11499     * <p>
11500     * Do not call this method directly.
11501     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11502     * </p>
11503     *
11504     * @param event The motion event to be dispatched.
11505     * @return True if the event was handled by the view, false otherwise.
11506     */
11507    protected boolean dispatchHoverEvent(MotionEvent event) {
11508        ListenerInfo li = mListenerInfo;
11509        //noinspection SimplifiableIfStatement
11510        if (li != null && li.mOnHoverListener != null
11511                && (mViewFlags & ENABLED_MASK) == ENABLED
11512                && li.mOnHoverListener.onHover(this, event)) {
11513            return true;
11514        }
11515
11516        return onHoverEvent(event);
11517    }
11518
11519    /**
11520     * Returns true if the view has a child to which it has recently sent
11521     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11522     * it does not have a hovered child, then it must be the innermost hovered view.
11523     * @hide
11524     */
11525    protected boolean hasHoveredChild() {
11526        return false;
11527    }
11528
11529    /**
11530     * Dispatch a generic motion event to the view under the first pointer.
11531     * <p>
11532     * Do not call this method directly.
11533     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11534     * </p>
11535     *
11536     * @param event The motion event to be dispatched.
11537     * @return True if the event was handled by the view, false otherwise.
11538     */
11539    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11540        return false;
11541    }
11542
11543    /**
11544     * Dispatch a generic motion event to the currently focused view.
11545     * <p>
11546     * Do not call this method directly.
11547     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11548     * </p>
11549     *
11550     * @param event The motion event to be dispatched.
11551     * @return True if the event was handled by the view, false otherwise.
11552     */
11553    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11554        return false;
11555    }
11556
11557    /**
11558     * Dispatch a pointer event.
11559     * <p>
11560     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
11561     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
11562     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
11563     * and should not be expected to handle other pointing device features.
11564     * </p>
11565     *
11566     * @param event The motion event to be dispatched.
11567     * @return True if the event was handled by the view, false otherwise.
11568     * @hide
11569     */
11570    public final boolean dispatchPointerEvent(MotionEvent event) {
11571        if (event.isTouchEvent()) {
11572            return dispatchTouchEvent(event);
11573        } else {
11574            return dispatchGenericMotionEvent(event);
11575        }
11576    }
11577
11578    /**
11579     * Called when the window containing this view gains or loses window focus.
11580     * ViewGroups should override to route to their children.
11581     *
11582     * @param hasFocus True if the window containing this view now has focus,
11583     *        false otherwise.
11584     */
11585    public void dispatchWindowFocusChanged(boolean hasFocus) {
11586        onWindowFocusChanged(hasFocus);
11587    }
11588
11589    /**
11590     * Called when the window containing this view gains or loses focus.  Note
11591     * that this is separate from view focus: to receive key events, both
11592     * your view and its window must have focus.  If a window is displayed
11593     * on top of yours that takes input focus, then your own window will lose
11594     * focus but the view focus will remain unchanged.
11595     *
11596     * @param hasWindowFocus True if the window containing this view now has
11597     *        focus, false otherwise.
11598     */
11599    public void onWindowFocusChanged(boolean hasWindowFocus) {
11600        InputMethodManager imm = InputMethodManager.peekInstance();
11601        if (!hasWindowFocus) {
11602            if (isPressed()) {
11603                setPressed(false);
11604            }
11605            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11606            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11607                imm.focusOut(this);
11608            }
11609            removeLongPressCallback();
11610            removeTapCallback();
11611            onFocusLost();
11612        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11613            imm.focusIn(this);
11614        }
11615
11616        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
11617
11618        refreshDrawableState();
11619    }
11620
11621    /**
11622     * Returns true if this view is in a window that currently has window focus.
11623     * Note that this is not the same as the view itself having focus.
11624     *
11625     * @return True if this view is in a window that currently has window focus.
11626     */
11627    public boolean hasWindowFocus() {
11628        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
11629    }
11630
11631    /**
11632     * Dispatch a view visibility change down the view hierarchy.
11633     * ViewGroups should override to route to their children.
11634     * @param changedView The view whose visibility changed. Could be 'this' or
11635     * an ancestor view.
11636     * @param visibility The new visibility of changedView: {@link #VISIBLE},
11637     * {@link #INVISIBLE} or {@link #GONE}.
11638     */
11639    protected void dispatchVisibilityChanged(@NonNull View changedView,
11640            @Visibility int visibility) {
11641        onVisibilityChanged(changedView, visibility);
11642    }
11643
11644    /**
11645     * Called when the visibility of the view or an ancestor of the view has
11646     * changed.
11647     *
11648     * @param changedView The view whose visibility changed. May be
11649     *                    {@code this} or an ancestor view.
11650     * @param visibility The new visibility, one of {@link #VISIBLE},
11651     *                   {@link #INVISIBLE} or {@link #GONE}.
11652     */
11653    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
11654    }
11655
11656    /**
11657     * Dispatch a hint about whether this view is displayed. For instance, when
11658     * a View moves out of the screen, it might receives a display hint indicating
11659     * the view is not displayed. Applications should not <em>rely</em> on this hint
11660     * as there is no guarantee that they will receive one.
11661     *
11662     * @param hint A hint about whether or not this view is displayed:
11663     * {@link #VISIBLE} or {@link #INVISIBLE}.
11664     */
11665    public void dispatchDisplayHint(@Visibility int hint) {
11666        onDisplayHint(hint);
11667    }
11668
11669    /**
11670     * Gives this view a hint about whether is displayed or not. For instance, when
11671     * a View moves out of the screen, it might receives a display hint indicating
11672     * the view is not displayed. Applications should not <em>rely</em> on this hint
11673     * as there is no guarantee that they will receive one.
11674     *
11675     * @param hint A hint about whether or not this view is displayed:
11676     * {@link #VISIBLE} or {@link #INVISIBLE}.
11677     */
11678    protected void onDisplayHint(@Visibility int hint) {
11679    }
11680
11681    /**
11682     * Dispatch a window visibility change down the view hierarchy.
11683     * ViewGroups should override to route to their children.
11684     *
11685     * @param visibility The new visibility of the window.
11686     *
11687     * @see #onWindowVisibilityChanged(int)
11688     */
11689    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
11690        onWindowVisibilityChanged(visibility);
11691    }
11692
11693    /**
11694     * Called when the window containing has change its visibility
11695     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
11696     * that this tells you whether or not your window is being made visible
11697     * to the window manager; this does <em>not</em> tell you whether or not
11698     * your window is obscured by other windows on the screen, even if it
11699     * is itself visible.
11700     *
11701     * @param visibility The new visibility of the window.
11702     */
11703    protected void onWindowVisibilityChanged(@Visibility int visibility) {
11704        if (visibility == VISIBLE) {
11705            initialAwakenScrollBars();
11706        }
11707    }
11708
11709    /**
11710     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
11711     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
11712     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
11713     *
11714     * @param isVisible true if this view's visibility to the user is uninterrupted by its
11715     *                  ancestors or by window visibility
11716     * @return true if this view is visible to the user, not counting clipping or overlapping
11717     */
11718    boolean dispatchVisibilityAggregated(boolean isVisible) {
11719        final boolean thisVisible = getVisibility() == VISIBLE;
11720        // If we're not visible but something is telling us we are, ignore it.
11721        if (thisVisible || !isVisible) {
11722            onVisibilityAggregated(isVisible);
11723        }
11724        return thisVisible && isVisible;
11725    }
11726
11727    /**
11728     * Called when the user-visibility of this View is potentially affected by a change
11729     * to this view itself, an ancestor view or the window this view is attached to.
11730     *
11731     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
11732     *                  and this view's window is also visible
11733     */
11734    @CallSuper
11735    public void onVisibilityAggregated(boolean isVisible) {
11736        if (isVisible && mAttachInfo != null) {
11737            initialAwakenScrollBars();
11738        }
11739
11740        final Drawable dr = mBackground;
11741        if (dr != null && isVisible != dr.isVisible()) {
11742            dr.setVisible(isVisible, false);
11743        }
11744        final Drawable hl = mDefaultFocusHighlight;
11745        if (hl != null && isVisible != hl.isVisible()) {
11746            hl.setVisible(isVisible, false);
11747        }
11748        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
11749        if (fg != null && isVisible != fg.isVisible()) {
11750            fg.setVisible(isVisible, false);
11751        }
11752
11753        if (isAutofillable()) {
11754            AutofillManager afm = getAutofillManager();
11755
11756            if (afm != null && getAccessibilityViewId() > LAST_APP_ACCESSIBILITY_ID) {
11757                if (mVisibilityChangeForAutofillHandler != null) {
11758                    mVisibilityChangeForAutofillHandler.removeMessages(0);
11759                }
11760
11761                // If the view is in the background but still part of the hierarchy this is called
11762                // with isVisible=false. Hence visibility==false requires further checks
11763                if (isVisible) {
11764                    afm.notifyViewVisibilityChange(this, true);
11765                } else {
11766                    if (mVisibilityChangeForAutofillHandler == null) {
11767                        mVisibilityChangeForAutofillHandler =
11768                                new VisibilityChangeForAutofillHandler(afm, this);
11769                    }
11770                    // Let current operation (e.g. removal of the view from the hierarchy)
11771                    // finish before checking state
11772                    mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
11773                }
11774            }
11775        }
11776    }
11777
11778    /**
11779     * Returns the current visibility of the window this view is attached to
11780     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
11781     *
11782     * @return Returns the current visibility of the view's window.
11783     */
11784    @Visibility
11785    public int getWindowVisibility() {
11786        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
11787    }
11788
11789    /**
11790     * Retrieve the overall visible display size in which the window this view is
11791     * attached to has been positioned in.  This takes into account screen
11792     * decorations above the window, for both cases where the window itself
11793     * is being position inside of them or the window is being placed under
11794     * then and covered insets are used for the window to position its content
11795     * inside.  In effect, this tells you the available area where content can
11796     * be placed and remain visible to users.
11797     *
11798     * <p>This function requires an IPC back to the window manager to retrieve
11799     * the requested information, so should not be used in performance critical
11800     * code like drawing.
11801     *
11802     * @param outRect Filled in with the visible display frame.  If the view
11803     * is not attached to a window, this is simply the raw display size.
11804     */
11805    public void getWindowVisibleDisplayFrame(Rect outRect) {
11806        if (mAttachInfo != null) {
11807            try {
11808                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11809            } catch (RemoteException e) {
11810                return;
11811            }
11812            // XXX This is really broken, and probably all needs to be done
11813            // in the window manager, and we need to know more about whether
11814            // we want the area behind or in front of the IME.
11815            final Rect insets = mAttachInfo.mVisibleInsets;
11816            outRect.left += insets.left;
11817            outRect.top += insets.top;
11818            outRect.right -= insets.right;
11819            outRect.bottom -= insets.bottom;
11820            return;
11821        }
11822        // The view is not attached to a display so we don't have a context.
11823        // Make a best guess about the display size.
11824        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11825        d.getRectSize(outRect);
11826    }
11827
11828    /**
11829     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
11830     * is currently in without any insets.
11831     *
11832     * @hide
11833     */
11834    public void getWindowDisplayFrame(Rect outRect) {
11835        if (mAttachInfo != null) {
11836            try {
11837                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
11838            } catch (RemoteException e) {
11839                return;
11840            }
11841            return;
11842        }
11843        // The view is not attached to a display so we don't have a context.
11844        // Make a best guess about the display size.
11845        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
11846        d.getRectSize(outRect);
11847    }
11848
11849    /**
11850     * Dispatch a notification about a resource configuration change down
11851     * the view hierarchy.
11852     * ViewGroups should override to route to their children.
11853     *
11854     * @param newConfig The new resource configuration.
11855     *
11856     * @see #onConfigurationChanged(android.content.res.Configuration)
11857     */
11858    public void dispatchConfigurationChanged(Configuration newConfig) {
11859        onConfigurationChanged(newConfig);
11860    }
11861
11862    /**
11863     * Called when the current configuration of the resources being used
11864     * by the application have changed.  You can use this to decide when
11865     * to reload resources that can changed based on orientation and other
11866     * configuration characteristics.  You only need to use this if you are
11867     * not relying on the normal {@link android.app.Activity} mechanism of
11868     * recreating the activity instance upon a configuration change.
11869     *
11870     * @param newConfig The new resource configuration.
11871     */
11872    protected void onConfigurationChanged(Configuration newConfig) {
11873    }
11874
11875    /**
11876     * Private function to aggregate all per-view attributes in to the view
11877     * root.
11878     */
11879    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11880        performCollectViewAttributes(attachInfo, visibility);
11881    }
11882
11883    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
11884        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
11885            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
11886                attachInfo.mKeepScreenOn = true;
11887            }
11888            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
11889            ListenerInfo li = mListenerInfo;
11890            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
11891                attachInfo.mHasSystemUiListeners = true;
11892            }
11893        }
11894    }
11895
11896    void needGlobalAttributesUpdate(boolean force) {
11897        final AttachInfo ai = mAttachInfo;
11898        if (ai != null && !ai.mRecomputeGlobalAttributes) {
11899            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
11900                    || ai.mHasSystemUiListeners) {
11901                ai.mRecomputeGlobalAttributes = true;
11902            }
11903        }
11904    }
11905
11906    /**
11907     * Returns whether the device is currently in touch mode.  Touch mode is entered
11908     * once the user begins interacting with the device by touch, and affects various
11909     * things like whether focus is always visible to the user.
11910     *
11911     * @return Whether the device is in touch mode.
11912     */
11913    @ViewDebug.ExportedProperty
11914    public boolean isInTouchMode() {
11915        if (mAttachInfo != null) {
11916            return mAttachInfo.mInTouchMode;
11917        } else {
11918            return ViewRootImpl.isInTouchMode();
11919        }
11920    }
11921
11922    /**
11923     * Returns the context the view is running in, through which it can
11924     * access the current theme, resources, etc.
11925     *
11926     * @return The view's Context.
11927     */
11928    @ViewDebug.CapturedViewProperty
11929    public final Context getContext() {
11930        return mContext;
11931    }
11932
11933    /**
11934     * Handle a key event before it is processed by any input method
11935     * associated with the view hierarchy.  This can be used to intercept
11936     * key events in special situations before the IME consumes them; a
11937     * typical example would be handling the BACK key to update the application's
11938     * UI instead of allowing the IME to see it and close itself.
11939     *
11940     * @param keyCode The value in event.getKeyCode().
11941     * @param event Description of the key event.
11942     * @return If you handled the event, return true. If you want to allow the
11943     *         event to be handled by the next receiver, return false.
11944     */
11945    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
11946        return false;
11947    }
11948
11949    /**
11950     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
11951     * KeyEvent.Callback.onKeyDown()}: perform press of the view
11952     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
11953     * is released, if the view is enabled and clickable.
11954     * <p>
11955     * Key presses in software keyboards will generally NOT trigger this
11956     * listener, although some may elect to do so in some situations. Do not
11957     * rely on this to catch software key presses.
11958     *
11959     * @param keyCode a key code that represents the button pressed, from
11960     *                {@link android.view.KeyEvent}
11961     * @param event the KeyEvent object that defines the button action
11962     */
11963    public boolean onKeyDown(int keyCode, KeyEvent event) {
11964        if (KeyEvent.isConfirmKey(keyCode)) {
11965            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
11966                return true;
11967            }
11968
11969            if (event.getRepeatCount() == 0) {
11970                // Long clickable items don't necessarily have to be clickable.
11971                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
11972                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
11973                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
11974                    // For the purposes of menu anchoring and drawable hotspots,
11975                    // key events are considered to be at the center of the view.
11976                    final float x = getWidth() / 2f;
11977                    final float y = getHeight() / 2f;
11978                    if (clickable) {
11979                        setPressed(true, x, y);
11980                    }
11981                    checkForLongClick(0, x, y);
11982                    return true;
11983                }
11984            }
11985        }
11986
11987        return false;
11988    }
11989
11990    /**
11991     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
11992     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
11993     * the event).
11994     * <p>Key presses in software keyboards will generally NOT trigger this listener,
11995     * although some may elect to do so in some situations. Do not rely on this to
11996     * catch software key presses.
11997     */
11998    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
11999        return false;
12000    }
12001
12002    /**
12003     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
12004     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
12005     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
12006     * or {@link KeyEvent#KEYCODE_SPACE} is released.
12007     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12008     * although some may elect to do so in some situations. Do not rely on this to
12009     * catch software key presses.
12010     *
12011     * @param keyCode A key code that represents the button pressed, from
12012     *                {@link android.view.KeyEvent}.
12013     * @param event   The KeyEvent object that defines the button action.
12014     */
12015    public boolean onKeyUp(int keyCode, KeyEvent event) {
12016        if (KeyEvent.isConfirmKey(keyCode)) {
12017            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12018                return true;
12019            }
12020            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
12021                setPressed(false);
12022
12023                if (!mHasPerformedLongPress) {
12024                    // This is a tap, so remove the longpress check
12025                    removeLongPressCallback();
12026                    if (!event.isCanceled()) {
12027                        return performClick();
12028                    }
12029                }
12030            }
12031        }
12032        return false;
12033    }
12034
12035    /**
12036     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
12037     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
12038     * the event).
12039     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12040     * although some may elect to do so in some situations. Do not rely on this to
12041     * catch software key presses.
12042     *
12043     * @param keyCode     A key code that represents the button pressed, from
12044     *                    {@link android.view.KeyEvent}.
12045     * @param repeatCount The number of times the action was made.
12046     * @param event       The KeyEvent object that defines the button action.
12047     */
12048    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
12049        return false;
12050    }
12051
12052    /**
12053     * Called on the focused view when a key shortcut event is not handled.
12054     * Override this method to implement local key shortcuts for the View.
12055     * Key shortcuts can also be implemented by setting the
12056     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
12057     *
12058     * @param keyCode The value in event.getKeyCode().
12059     * @param event Description of the key event.
12060     * @return If you handled the event, return true. If you want to allow the
12061     *         event to be handled by the next receiver, return false.
12062     */
12063    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
12064        return false;
12065    }
12066
12067    /**
12068     * Check whether the called view is a text editor, in which case it
12069     * would make sense to automatically display a soft input window for
12070     * it.  Subclasses should override this if they implement
12071     * {@link #onCreateInputConnection(EditorInfo)} to return true if
12072     * a call on that method would return a non-null InputConnection, and
12073     * they are really a first-class editor that the user would normally
12074     * start typing on when the go into a window containing your view.
12075     *
12076     * <p>The default implementation always returns false.  This does
12077     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
12078     * will not be called or the user can not otherwise perform edits on your
12079     * view; it is just a hint to the system that this is not the primary
12080     * purpose of this view.
12081     *
12082     * @return Returns true if this view is a text editor, else false.
12083     */
12084    public boolean onCheckIsTextEditor() {
12085        return false;
12086    }
12087
12088    /**
12089     * Create a new InputConnection for an InputMethod to interact
12090     * with the view.  The default implementation returns null, since it doesn't
12091     * support input methods.  You can override this to implement such support.
12092     * This is only needed for views that take focus and text input.
12093     *
12094     * <p>When implementing this, you probably also want to implement
12095     * {@link #onCheckIsTextEditor()} to indicate you will return a
12096     * non-null InputConnection.</p>
12097     *
12098     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12099     * object correctly and in its entirety, so that the connected IME can rely
12100     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12101     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12102     * must be filled in with the correct cursor position for IMEs to work correctly
12103     * with your application.</p>
12104     *
12105     * @param outAttrs Fill in with attribute information about the connection.
12106     */
12107    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12108        return null;
12109    }
12110
12111    /**
12112     * Called by the {@link android.view.inputmethod.InputMethodManager}
12113     * when a view who is not the current
12114     * input connection target is trying to make a call on the manager.  The
12115     * default implementation returns false; you can override this to return
12116     * true for certain views if you are performing InputConnection proxying
12117     * to them.
12118     * @param view The View that is making the InputMethodManager call.
12119     * @return Return true to allow the call, false to reject.
12120     */
12121    public boolean checkInputConnectionProxy(View view) {
12122        return false;
12123    }
12124
12125    /**
12126     * Show the context menu for this view. It is not safe to hold on to the
12127     * menu after returning from this method.
12128     *
12129     * You should normally not overload this method. Overload
12130     * {@link #onCreateContextMenu(ContextMenu)} or define an
12131     * {@link OnCreateContextMenuListener} to add items to the context menu.
12132     *
12133     * @param menu The context menu to populate
12134     */
12135    public void createContextMenu(ContextMenu menu) {
12136        ContextMenuInfo menuInfo = getContextMenuInfo();
12137
12138        // Sets the current menu info so all items added to menu will have
12139        // my extra info set.
12140        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12141
12142        onCreateContextMenu(menu);
12143        ListenerInfo li = mListenerInfo;
12144        if (li != null && li.mOnCreateContextMenuListener != null) {
12145            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12146        }
12147
12148        // Clear the extra information so subsequent items that aren't mine don't
12149        // have my extra info.
12150        ((MenuBuilder)menu).setCurrentMenuInfo(null);
12151
12152        if (mParent != null) {
12153            mParent.createContextMenu(menu);
12154        }
12155    }
12156
12157    /**
12158     * Views should implement this if they have extra information to associate
12159     * with the context menu. The return result is supplied as a parameter to
12160     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12161     * callback.
12162     *
12163     * @return Extra information about the item for which the context menu
12164     *         should be shown. This information will vary across different
12165     *         subclasses of View.
12166     */
12167    protected ContextMenuInfo getContextMenuInfo() {
12168        return null;
12169    }
12170
12171    /**
12172     * Views should implement this if the view itself is going to add items to
12173     * the context menu.
12174     *
12175     * @param menu the context menu to populate
12176     */
12177    protected void onCreateContextMenu(ContextMenu menu) {
12178    }
12179
12180    /**
12181     * Implement this method to handle trackball motion events.  The
12182     * <em>relative</em> movement of the trackball since the last event
12183     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12184     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12185     * that a movement of 1 corresponds to the user pressing one DPAD key (so
12186     * they will often be fractional values, representing the more fine-grained
12187     * movement information available from a trackball).
12188     *
12189     * @param event The motion event.
12190     * @return True if the event was handled, false otherwise.
12191     */
12192    public boolean onTrackballEvent(MotionEvent event) {
12193        return false;
12194    }
12195
12196    /**
12197     * Implement this method to handle generic motion events.
12198     * <p>
12199     * Generic motion events describe joystick movements, mouse hovers, track pad
12200     * touches, scroll wheel movements and other input events.  The
12201     * {@link MotionEvent#getSource() source} of the motion event specifies
12202     * the class of input that was received.  Implementations of this method
12203     * must examine the bits in the source before processing the event.
12204     * The following code example shows how this is done.
12205     * </p><p>
12206     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12207     * are delivered to the view under the pointer.  All other generic motion events are
12208     * delivered to the focused view.
12209     * </p>
12210     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12211     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12212     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12213     *             // process the joystick movement...
12214     *             return true;
12215     *         }
12216     *     }
12217     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12218     *         switch (event.getAction()) {
12219     *             case MotionEvent.ACTION_HOVER_MOVE:
12220     *                 // process the mouse hover movement...
12221     *                 return true;
12222     *             case MotionEvent.ACTION_SCROLL:
12223     *                 // process the scroll wheel movement...
12224     *                 return true;
12225     *         }
12226     *     }
12227     *     return super.onGenericMotionEvent(event);
12228     * }</pre>
12229     *
12230     * @param event The generic motion event being processed.
12231     * @return True if the event was handled, false otherwise.
12232     */
12233    public boolean onGenericMotionEvent(MotionEvent event) {
12234        return false;
12235    }
12236
12237    /**
12238     * Implement this method to handle hover events.
12239     * <p>
12240     * This method is called whenever a pointer is hovering into, over, or out of the
12241     * bounds of a view and the view is not currently being touched.
12242     * Hover events are represented as pointer events with action
12243     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12244     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12245     * </p>
12246     * <ul>
12247     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12248     * when the pointer enters the bounds of the view.</li>
12249     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12250     * when the pointer has already entered the bounds of the view and has moved.</li>
12251     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12252     * when the pointer has exited the bounds of the view or when the pointer is
12253     * about to go down due to a button click, tap, or similar user action that
12254     * causes the view to be touched.</li>
12255     * </ul>
12256     * <p>
12257     * The view should implement this method to return true to indicate that it is
12258     * handling the hover event, such as by changing its drawable state.
12259     * </p><p>
12260     * The default implementation calls {@link #setHovered} to update the hovered state
12261     * of the view when a hover enter or hover exit event is received, if the view
12262     * is enabled and is clickable.  The default implementation also sends hover
12263     * accessibility events.
12264     * </p>
12265     *
12266     * @param event The motion event that describes the hover.
12267     * @return True if the view handled the hover event.
12268     *
12269     * @see #isHovered
12270     * @see #setHovered
12271     * @see #onHoverChanged
12272     */
12273    public boolean onHoverEvent(MotionEvent event) {
12274        // The root view may receive hover (or touch) events that are outside the bounds of
12275        // the window.  This code ensures that we only send accessibility events for
12276        // hovers that are actually within the bounds of the root view.
12277        final int action = event.getActionMasked();
12278        if (!mSendingHoverAccessibilityEvents) {
12279            if ((action == MotionEvent.ACTION_HOVER_ENTER
12280                    || action == MotionEvent.ACTION_HOVER_MOVE)
12281                    && !hasHoveredChild()
12282                    && pointInView(event.getX(), event.getY())) {
12283                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12284                mSendingHoverAccessibilityEvents = true;
12285            }
12286        } else {
12287            if (action == MotionEvent.ACTION_HOVER_EXIT
12288                    || (action == MotionEvent.ACTION_MOVE
12289                            && !pointInView(event.getX(), event.getY()))) {
12290                mSendingHoverAccessibilityEvents = false;
12291                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12292            }
12293        }
12294
12295        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12296                && event.isFromSource(InputDevice.SOURCE_MOUSE)
12297                && isOnScrollbar(event.getX(), event.getY())) {
12298            awakenScrollBars();
12299        }
12300
12301        // If we consider ourself hoverable, or if we we're already hovered,
12302        // handle changing state in response to ENTER and EXIT events.
12303        if (isHoverable() || isHovered()) {
12304            switch (action) {
12305                case MotionEvent.ACTION_HOVER_ENTER:
12306                    setHovered(true);
12307                    break;
12308                case MotionEvent.ACTION_HOVER_EXIT:
12309                    setHovered(false);
12310                    break;
12311            }
12312
12313            // Dispatch the event to onGenericMotionEvent before returning true.
12314            // This is to provide compatibility with existing applications that
12315            // handled HOVER_MOVE events in onGenericMotionEvent and that would
12316            // break because of the new default handling for hoverable views
12317            // in onHoverEvent.
12318            // Note that onGenericMotionEvent will be called by default when
12319            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12320            dispatchGenericMotionEventInternal(event);
12321            // The event was already handled by calling setHovered(), so always
12322            // return true.
12323            return true;
12324        }
12325
12326        return false;
12327    }
12328
12329    /**
12330     * Returns true if the view should handle {@link #onHoverEvent}
12331     * by calling {@link #setHovered} to change its hovered state.
12332     *
12333     * @return True if the view is hoverable.
12334     */
12335    private boolean isHoverable() {
12336        final int viewFlags = mViewFlags;
12337        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12338            return false;
12339        }
12340
12341        return (viewFlags & CLICKABLE) == CLICKABLE
12342                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12343                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12344    }
12345
12346    /**
12347     * Returns true if the view is currently hovered.
12348     *
12349     * @return True if the view is currently hovered.
12350     *
12351     * @see #setHovered
12352     * @see #onHoverChanged
12353     */
12354    @ViewDebug.ExportedProperty
12355    public boolean isHovered() {
12356        return (mPrivateFlags & PFLAG_HOVERED) != 0;
12357    }
12358
12359    /**
12360     * Sets whether the view is currently hovered.
12361     * <p>
12362     * Calling this method also changes the drawable state of the view.  This
12363     * enables the view to react to hover by using different drawable resources
12364     * to change its appearance.
12365     * </p><p>
12366     * The {@link #onHoverChanged} method is called when the hovered state changes.
12367     * </p>
12368     *
12369     * @param hovered True if the view is hovered.
12370     *
12371     * @see #isHovered
12372     * @see #onHoverChanged
12373     */
12374    public void setHovered(boolean hovered) {
12375        if (hovered) {
12376            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12377                mPrivateFlags |= PFLAG_HOVERED;
12378                refreshDrawableState();
12379                onHoverChanged(true);
12380            }
12381        } else {
12382            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12383                mPrivateFlags &= ~PFLAG_HOVERED;
12384                refreshDrawableState();
12385                onHoverChanged(false);
12386            }
12387        }
12388    }
12389
12390    /**
12391     * Implement this method to handle hover state changes.
12392     * <p>
12393     * This method is called whenever the hover state changes as a result of a
12394     * call to {@link #setHovered}.
12395     * </p>
12396     *
12397     * @param hovered The current hover state, as returned by {@link #isHovered}.
12398     *
12399     * @see #isHovered
12400     * @see #setHovered
12401     */
12402    public void onHoverChanged(boolean hovered) {
12403    }
12404
12405    /**
12406     * Handles scroll bar dragging by mouse input.
12407     *
12408     * @hide
12409     * @param event The motion event.
12410     *
12411     * @return true if the event was handled as a scroll bar dragging, false otherwise.
12412     */
12413    protected boolean handleScrollBarDragging(MotionEvent event) {
12414        if (mScrollCache == null) {
12415            return false;
12416        }
12417        final float x = event.getX();
12418        final float y = event.getY();
12419        final int action = event.getAction();
12420        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12421                && action != MotionEvent.ACTION_DOWN)
12422                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12423                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12424            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12425            return false;
12426        }
12427
12428        switch (action) {
12429            case MotionEvent.ACTION_MOVE:
12430                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12431                    return false;
12432                }
12433                if (mScrollCache.mScrollBarDraggingState
12434                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12435                    final Rect bounds = mScrollCache.mScrollBarBounds;
12436                    getVerticalScrollBarBounds(bounds, null);
12437                    final int range = computeVerticalScrollRange();
12438                    final int offset = computeVerticalScrollOffset();
12439                    final int extent = computeVerticalScrollExtent();
12440
12441                    final int thumbLength = ScrollBarUtils.getThumbLength(
12442                            bounds.height(), bounds.width(), extent, range);
12443                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12444                            bounds.height(), thumbLength, extent, range, offset);
12445
12446                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
12447                    final float maxThumbOffset = bounds.height() - thumbLength;
12448                    final float newThumbOffset =
12449                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12450                    final int height = getHeight();
12451                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12452                            && height > 0 && extent > 0) {
12453                        final int newY = Math.round((range - extent)
12454                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12455                        if (newY != getScrollY()) {
12456                            mScrollCache.mScrollBarDraggingPos = y;
12457                            setScrollY(newY);
12458                        }
12459                    }
12460                    return true;
12461                }
12462                if (mScrollCache.mScrollBarDraggingState
12463                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12464                    final Rect bounds = mScrollCache.mScrollBarBounds;
12465                    getHorizontalScrollBarBounds(bounds, null);
12466                    final int range = computeHorizontalScrollRange();
12467                    final int offset = computeHorizontalScrollOffset();
12468                    final int extent = computeHorizontalScrollExtent();
12469
12470                    final int thumbLength = ScrollBarUtils.getThumbLength(
12471                            bounds.width(), bounds.height(), extent, range);
12472                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12473                            bounds.width(), thumbLength, extent, range, offset);
12474
12475                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
12476                    final float maxThumbOffset = bounds.width() - thumbLength;
12477                    final float newThumbOffset =
12478                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12479                    final int width = getWidth();
12480                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12481                            && width > 0 && extent > 0) {
12482                        final int newX = Math.round((range - extent)
12483                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12484                        if (newX != getScrollX()) {
12485                            mScrollCache.mScrollBarDraggingPos = x;
12486                            setScrollX(newX);
12487                        }
12488                    }
12489                    return true;
12490                }
12491            case MotionEvent.ACTION_DOWN:
12492                if (mScrollCache.state == ScrollabilityCache.OFF) {
12493                    return false;
12494                }
12495                if (isOnVerticalScrollbarThumb(x, y)) {
12496                    mScrollCache.mScrollBarDraggingState =
12497                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12498                    mScrollCache.mScrollBarDraggingPos = y;
12499                    return true;
12500                }
12501                if (isOnHorizontalScrollbarThumb(x, y)) {
12502                    mScrollCache.mScrollBarDraggingState =
12503                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12504                    mScrollCache.mScrollBarDraggingPos = x;
12505                    return true;
12506                }
12507        }
12508        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12509        return false;
12510    }
12511
12512    /**
12513     * Implement this method to handle touch screen motion events.
12514     * <p>
12515     * If this method is used to detect click actions, it is recommended that
12516     * the actions be performed by implementing and calling
12517     * {@link #performClick()}. This will ensure consistent system behavior,
12518     * including:
12519     * <ul>
12520     * <li>obeying click sound preferences
12521     * <li>dispatching OnClickListener calls
12522     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12523     * accessibility features are enabled
12524     * </ul>
12525     *
12526     * @param event The motion event.
12527     * @return True if the event was handled, false otherwise.
12528     */
12529    public boolean onTouchEvent(MotionEvent event) {
12530        final float x = event.getX();
12531        final float y = event.getY();
12532        final int viewFlags = mViewFlags;
12533        final int action = event.getAction();
12534
12535        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12536                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12537                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12538
12539        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12540            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12541                setPressed(false);
12542            }
12543            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12544            // A disabled view that is clickable still consumes the touch
12545            // events, it just doesn't respond to them.
12546            return clickable;
12547        }
12548        if (mTouchDelegate != null) {
12549            if (mTouchDelegate.onTouchEvent(event)) {
12550                return true;
12551            }
12552        }
12553
12554        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12555            switch (action) {
12556                case MotionEvent.ACTION_UP:
12557                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12558                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
12559                        handleTooltipUp();
12560                    }
12561                    if (!clickable) {
12562                        removeTapCallback();
12563                        removeLongPressCallback();
12564                        mInContextButtonPress = false;
12565                        mHasPerformedLongPress = false;
12566                        mIgnoreNextUpEvent = false;
12567                        break;
12568                    }
12569                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
12570                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
12571                        // take focus if we don't have it already and we should in
12572                        // touch mode.
12573                        boolean focusTaken = false;
12574                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
12575                            focusTaken = requestFocus();
12576                        }
12577
12578                        if (prepressed) {
12579                            // The button is being released before we actually
12580                            // showed it as pressed.  Make it show the pressed
12581                            // state now (before scheduling the click) to ensure
12582                            // the user sees it.
12583                            setPressed(true, x, y);
12584                        }
12585
12586                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
12587                            // This is a tap, so remove the longpress check
12588                            removeLongPressCallback();
12589
12590                            // Only perform take click actions if we were in the pressed state
12591                            if (!focusTaken) {
12592                                // Use a Runnable and post this rather than calling
12593                                // performClick directly. This lets other visual state
12594                                // of the view update before click actions start.
12595                                if (mPerformClick == null) {
12596                                    mPerformClick = new PerformClick();
12597                                }
12598                                if (!post(mPerformClick)) {
12599                                    performClick();
12600                                }
12601                            }
12602                        }
12603
12604                        if (mUnsetPressedState == null) {
12605                            mUnsetPressedState = new UnsetPressedState();
12606                        }
12607
12608                        if (prepressed) {
12609                            postDelayed(mUnsetPressedState,
12610                                    ViewConfiguration.getPressedStateDuration());
12611                        } else if (!post(mUnsetPressedState)) {
12612                            // If the post failed, unpress right now
12613                            mUnsetPressedState.run();
12614                        }
12615
12616                        removeTapCallback();
12617                    }
12618                    mIgnoreNextUpEvent = false;
12619                    break;
12620
12621                case MotionEvent.ACTION_DOWN:
12622                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
12623                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
12624                    }
12625                    mHasPerformedLongPress = false;
12626
12627                    if (!clickable) {
12628                        checkForLongClick(0, x, y);
12629                        break;
12630                    }
12631
12632                    if (performButtonActionOnTouchDown(event)) {
12633                        break;
12634                    }
12635
12636                    // Walk up the hierarchy to determine if we're inside a scrolling container.
12637                    boolean isInScrollingContainer = isInScrollingContainer();
12638
12639                    // For views inside a scrolling container, delay the pressed feedback for
12640                    // a short period in case this is a scroll.
12641                    if (isInScrollingContainer) {
12642                        mPrivateFlags |= PFLAG_PREPRESSED;
12643                        if (mPendingCheckForTap == null) {
12644                            mPendingCheckForTap = new CheckForTap();
12645                        }
12646                        mPendingCheckForTap.x = event.getX();
12647                        mPendingCheckForTap.y = event.getY();
12648                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
12649                    } else {
12650                        // Not inside a scrolling container, so show the feedback right away
12651                        setPressed(true, x, y);
12652                        checkForLongClick(0, x, y);
12653                    }
12654                    break;
12655
12656                case MotionEvent.ACTION_CANCEL:
12657                    if (clickable) {
12658                        setPressed(false);
12659                    }
12660                    removeTapCallback();
12661                    removeLongPressCallback();
12662                    mInContextButtonPress = false;
12663                    mHasPerformedLongPress = false;
12664                    mIgnoreNextUpEvent = false;
12665                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12666                    break;
12667
12668                case MotionEvent.ACTION_MOVE:
12669                    if (clickable) {
12670                        drawableHotspotChanged(x, y);
12671                    }
12672
12673                    // Be lenient about moving outside of buttons
12674                    if (!pointInView(x, y, mTouchSlop)) {
12675                        // Outside button
12676                        // Remove any future long press/tap checks
12677                        removeTapCallback();
12678                        removeLongPressCallback();
12679                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
12680                            setPressed(false);
12681                        }
12682                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12683                    }
12684                    break;
12685            }
12686
12687            return true;
12688        }
12689
12690        return false;
12691    }
12692
12693    /**
12694     * @hide
12695     */
12696    public boolean isInScrollingContainer() {
12697        ViewParent p = getParent();
12698        while (p != null && p instanceof ViewGroup) {
12699            if (((ViewGroup) p).shouldDelayChildPressedState()) {
12700                return true;
12701            }
12702            p = p.getParent();
12703        }
12704        return false;
12705    }
12706
12707    /**
12708     * Remove the longpress detection timer.
12709     */
12710    private void removeLongPressCallback() {
12711        if (mPendingCheckForLongPress != null) {
12712            removeCallbacks(mPendingCheckForLongPress);
12713        }
12714    }
12715
12716    /**
12717     * Remove the pending click action
12718     */
12719    private void removePerformClickCallback() {
12720        if (mPerformClick != null) {
12721            removeCallbacks(mPerformClick);
12722        }
12723    }
12724
12725    /**
12726     * Remove the prepress detection timer.
12727     */
12728    private void removeUnsetPressCallback() {
12729        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
12730            setPressed(false);
12731            removeCallbacks(mUnsetPressedState);
12732        }
12733    }
12734
12735    /**
12736     * Remove the tap detection timer.
12737     */
12738    private void removeTapCallback() {
12739        if (mPendingCheckForTap != null) {
12740            mPrivateFlags &= ~PFLAG_PREPRESSED;
12741            removeCallbacks(mPendingCheckForTap);
12742        }
12743    }
12744
12745    /**
12746     * Cancels a pending long press.  Your subclass can use this if you
12747     * want the context menu to come up if the user presses and holds
12748     * at the same place, but you don't want it to come up if they press
12749     * and then move around enough to cause scrolling.
12750     */
12751    public void cancelLongPress() {
12752        removeLongPressCallback();
12753
12754        /*
12755         * The prepressed state handled by the tap callback is a display
12756         * construct, but the tap callback will post a long press callback
12757         * less its own timeout. Remove it here.
12758         */
12759        removeTapCallback();
12760    }
12761
12762    /**
12763     * Remove the pending callback for sending a
12764     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
12765     */
12766    private void removeSendViewScrolledAccessibilityEventCallback() {
12767        if (mSendViewScrolledAccessibilityEvent != null) {
12768            removeCallbacks(mSendViewScrolledAccessibilityEvent);
12769            mSendViewScrolledAccessibilityEvent.mIsPending = false;
12770        }
12771    }
12772
12773    /**
12774     * Sets the TouchDelegate for this View.
12775     */
12776    public void setTouchDelegate(TouchDelegate delegate) {
12777        mTouchDelegate = delegate;
12778    }
12779
12780    /**
12781     * Gets the TouchDelegate for this View.
12782     */
12783    public TouchDelegate getTouchDelegate() {
12784        return mTouchDelegate;
12785    }
12786
12787    /**
12788     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
12789     *
12790     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
12791     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
12792     * available. This method should only be called for touch events.
12793     *
12794     * <p class="note">This api is not intended for most applications. Buffered dispatch
12795     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
12796     * streams will not improve your input latency. Side effects include: increased latency,
12797     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
12798     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
12799     * you.</p>
12800     */
12801    public final void requestUnbufferedDispatch(MotionEvent event) {
12802        final int action = event.getAction();
12803        if (mAttachInfo == null
12804                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
12805                || !event.isTouchEvent()) {
12806            return;
12807        }
12808        mAttachInfo.mUnbufferedDispatchRequested = true;
12809    }
12810
12811    /**
12812     * Set flags controlling behavior of this view.
12813     *
12814     * @param flags Constant indicating the value which should be set
12815     * @param mask Constant indicating the bit range that should be changed
12816     */
12817    void setFlags(int flags, int mask) {
12818        final boolean accessibilityEnabled =
12819                AccessibilityManager.getInstance(mContext).isEnabled();
12820        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
12821
12822        int old = mViewFlags;
12823        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
12824
12825        int changed = mViewFlags ^ old;
12826        if (changed == 0) {
12827            return;
12828        }
12829        int privateFlags = mPrivateFlags;
12830
12831        // If focusable is auto, update the FOCUSABLE bit.
12832        int focusableChangedByAuto = 0;
12833        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
12834                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
12835            // Heuristic only takes into account whether view is clickable.
12836            final int newFocus;
12837            if ((mViewFlags & CLICKABLE) != 0) {
12838                newFocus = FOCUSABLE;
12839            } else {
12840                newFocus = NOT_FOCUSABLE;
12841            }
12842            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
12843            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
12844            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
12845        }
12846
12847        /* Check if the FOCUSABLE bit has changed */
12848        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
12849            if (((old & FOCUSABLE) == FOCUSABLE)
12850                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
12851                /* Give up focus if we are no longer focusable */
12852                clearFocus();
12853            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
12854                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
12855                /*
12856                 * Tell the view system that we are now available to take focus
12857                 * if no one else already has it.
12858                 */
12859                if (mParent != null) {
12860                    ViewRootImpl viewRootImpl = getViewRootImpl();
12861                    if (!sAutoFocusableOffUIThreadWontNotifyParents
12862                            || focusableChangedByAuto == 0
12863                            || viewRootImpl == null
12864                            || viewRootImpl.mThread == Thread.currentThread()) {
12865                        mParent.focusableViewAvailable(this);
12866                    }
12867                }
12868            }
12869        }
12870
12871        final int newVisibility = flags & VISIBILITY_MASK;
12872        if (newVisibility == VISIBLE) {
12873            if ((changed & VISIBILITY_MASK) != 0) {
12874                /*
12875                 * If this view is becoming visible, invalidate it in case it changed while
12876                 * it was not visible. Marking it drawn ensures that the invalidation will
12877                 * go through.
12878                 */
12879                mPrivateFlags |= PFLAG_DRAWN;
12880                invalidate(true);
12881
12882                needGlobalAttributesUpdate(true);
12883
12884                // a view becoming visible is worth notifying the parent
12885                // about in case nothing has focus.  even if this specific view
12886                // isn't focusable, it may contain something that is, so let
12887                // the root view try to give this focus if nothing else does.
12888                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
12889                    mParent.focusableViewAvailable(this);
12890                }
12891            }
12892        }
12893
12894        /* Check if the GONE bit has changed */
12895        if ((changed & GONE) != 0) {
12896            needGlobalAttributesUpdate(false);
12897            requestLayout();
12898
12899            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
12900                if (hasFocus()) clearFocus();
12901                clearAccessibilityFocus();
12902                destroyDrawingCache();
12903                if (mParent instanceof View) {
12904                    // GONE views noop invalidation, so invalidate the parent
12905                    ((View) mParent).invalidate(true);
12906                }
12907                // Mark the view drawn to ensure that it gets invalidated properly the next
12908                // time it is visible and gets invalidated
12909                mPrivateFlags |= PFLAG_DRAWN;
12910            }
12911            if (mAttachInfo != null) {
12912                mAttachInfo.mViewVisibilityChanged = true;
12913            }
12914        }
12915
12916        /* Check if the VISIBLE bit has changed */
12917        if ((changed & INVISIBLE) != 0) {
12918            needGlobalAttributesUpdate(false);
12919            /*
12920             * If this view is becoming invisible, set the DRAWN flag so that
12921             * the next invalidate() will not be skipped.
12922             */
12923            mPrivateFlags |= PFLAG_DRAWN;
12924
12925            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
12926                // root view becoming invisible shouldn't clear focus and accessibility focus
12927                if (getRootView() != this) {
12928                    if (hasFocus()) clearFocus();
12929                    clearAccessibilityFocus();
12930                }
12931            }
12932            if (mAttachInfo != null) {
12933                mAttachInfo.mViewVisibilityChanged = true;
12934            }
12935        }
12936
12937        if ((changed & VISIBILITY_MASK) != 0) {
12938            // If the view is invisible, cleanup its display list to free up resources
12939            if (newVisibility != VISIBLE && mAttachInfo != null) {
12940                cleanupDraw();
12941            }
12942
12943            if (mParent instanceof ViewGroup) {
12944                ((ViewGroup) mParent).onChildVisibilityChanged(this,
12945                        (changed & VISIBILITY_MASK), newVisibility);
12946                ((View) mParent).invalidate(true);
12947            } else if (mParent != null) {
12948                mParent.invalidateChild(this, null);
12949            }
12950
12951            if (mAttachInfo != null) {
12952                dispatchVisibilityChanged(this, newVisibility);
12953
12954                // Aggregated visibility changes are dispatched to attached views
12955                // in visible windows where the parent is currently shown/drawn
12956                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
12957                // discounting clipping or overlapping. This makes it a good place
12958                // to change animation states.
12959                if (mParent != null && getWindowVisibility() == VISIBLE &&
12960                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
12961                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
12962                }
12963                notifySubtreeAccessibilityStateChangedIfNeeded();
12964            }
12965        }
12966
12967        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
12968            destroyDrawingCache();
12969        }
12970
12971        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
12972            destroyDrawingCache();
12973            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12974            invalidateParentCaches();
12975        }
12976
12977        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
12978            destroyDrawingCache();
12979            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12980        }
12981
12982        if ((changed & DRAW_MASK) != 0) {
12983            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
12984                if (mBackground != null
12985                        || mDefaultFocusHighlight != null
12986                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
12987                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12988                } else {
12989                    mPrivateFlags |= PFLAG_SKIP_DRAW;
12990                }
12991            } else {
12992                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
12993            }
12994            requestLayout();
12995            invalidate(true);
12996        }
12997
12998        if ((changed & KEEP_SCREEN_ON) != 0) {
12999            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13000                mParent.recomputeViewAttributes(this);
13001            }
13002        }
13003
13004        if (accessibilityEnabled) {
13005            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
13006                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
13007                    || (changed & CONTEXT_CLICKABLE) != 0) {
13008                if (oldIncludeForAccessibility != includeForAccessibility()) {
13009                    notifySubtreeAccessibilityStateChangedIfNeeded();
13010                } else {
13011                    notifyViewAccessibilityStateChangedIfNeeded(
13012                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13013                }
13014            } else if ((changed & ENABLED_MASK) != 0) {
13015                notifyViewAccessibilityStateChangedIfNeeded(
13016                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13017            }
13018        }
13019    }
13020
13021    /**
13022     * Change the view's z order in the tree, so it's on top of other sibling
13023     * views. This ordering change may affect layout, if the parent container
13024     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
13025     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
13026     * method should be followed by calls to {@link #requestLayout()} and
13027     * {@link View#invalidate()} on the view's parent to force the parent to redraw
13028     * with the new child ordering.
13029     *
13030     * @see ViewGroup#bringChildToFront(View)
13031     */
13032    public void bringToFront() {
13033        if (mParent != null) {
13034            mParent.bringChildToFront(this);
13035        }
13036    }
13037
13038    /**
13039     * This is called in response to an internal scroll in this view (i.e., the
13040     * view scrolled its own contents). This is typically as a result of
13041     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
13042     * called.
13043     *
13044     * @param l Current horizontal scroll origin.
13045     * @param t Current vertical scroll origin.
13046     * @param oldl Previous horizontal scroll origin.
13047     * @param oldt Previous vertical scroll origin.
13048     */
13049    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
13050        notifySubtreeAccessibilityStateChangedIfNeeded();
13051
13052        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13053            postSendViewScrolledAccessibilityEventCallback();
13054        }
13055
13056        mBackgroundSizeChanged = true;
13057        mDefaultFocusHighlightSizeChanged = true;
13058        if (mForegroundInfo != null) {
13059            mForegroundInfo.mBoundsChanged = true;
13060        }
13061
13062        final AttachInfo ai = mAttachInfo;
13063        if (ai != null) {
13064            ai.mViewScrollChanged = true;
13065        }
13066
13067        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
13068            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
13069        }
13070    }
13071
13072    /**
13073     * Interface definition for a callback to be invoked when the scroll
13074     * X or Y positions of a view change.
13075     * <p>
13076     * <b>Note:</b> Some views handle scrolling independently from View and may
13077     * have their own separate listeners for scroll-type events. For example,
13078     * {@link android.widget.ListView ListView} allows clients to register an
13079     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
13080     * to listen for changes in list scroll position.
13081     *
13082     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
13083     */
13084    public interface OnScrollChangeListener {
13085        /**
13086         * Called when the scroll position of a view changes.
13087         *
13088         * @param v The view whose scroll position has changed.
13089         * @param scrollX Current horizontal scroll origin.
13090         * @param scrollY Current vertical scroll origin.
13091         * @param oldScrollX Previous horizontal scroll origin.
13092         * @param oldScrollY Previous vertical scroll origin.
13093         */
13094        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13095    }
13096
13097    /**
13098     * Interface definition for a callback to be invoked when the layout bounds of a view
13099     * changes due to layout processing.
13100     */
13101    public interface OnLayoutChangeListener {
13102        /**
13103         * Called when the layout bounds of a view changes due to layout processing.
13104         *
13105         * @param v The view whose bounds have changed.
13106         * @param left The new value of the view's left property.
13107         * @param top The new value of the view's top property.
13108         * @param right The new value of the view's right property.
13109         * @param bottom The new value of the view's bottom property.
13110         * @param oldLeft The previous value of the view's left property.
13111         * @param oldTop The previous value of the view's top property.
13112         * @param oldRight The previous value of the view's right property.
13113         * @param oldBottom The previous value of the view's bottom property.
13114         */
13115        void onLayoutChange(View v, int left, int top, int right, int bottom,
13116            int oldLeft, int oldTop, int oldRight, int oldBottom);
13117    }
13118
13119    /**
13120     * This is called during layout when the size of this view has changed. If
13121     * you were just added to the view hierarchy, you're called with the old
13122     * values of 0.
13123     *
13124     * @param w Current width of this view.
13125     * @param h Current height of this view.
13126     * @param oldw Old width of this view.
13127     * @param oldh Old height of this view.
13128     */
13129    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13130    }
13131
13132    /**
13133     * Called by draw to draw the child views. This may be overridden
13134     * by derived classes to gain control just before its children are drawn
13135     * (but after its own view has been drawn).
13136     * @param canvas the canvas on which to draw the view
13137     */
13138    protected void dispatchDraw(Canvas canvas) {
13139
13140    }
13141
13142    /**
13143     * Gets the parent of this view. Note that the parent is a
13144     * ViewParent and not necessarily a View.
13145     *
13146     * @return Parent of this view.
13147     */
13148    public final ViewParent getParent() {
13149        return mParent;
13150    }
13151
13152    /**
13153     * Set the horizontal scrolled position of your view. This will cause a call to
13154     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13155     * invalidated.
13156     * @param value the x position to scroll to
13157     */
13158    public void setScrollX(int value) {
13159        scrollTo(value, mScrollY);
13160    }
13161
13162    /**
13163     * Set the vertical scrolled position of your view. This will cause a call to
13164     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13165     * invalidated.
13166     * @param value the y position to scroll to
13167     */
13168    public void setScrollY(int value) {
13169        scrollTo(mScrollX, value);
13170    }
13171
13172    /**
13173     * Return the scrolled left position of this view. This is the left edge of
13174     * the displayed part of your view. You do not need to draw any pixels
13175     * farther left, since those are outside of the frame of your view on
13176     * screen.
13177     *
13178     * @return The left edge of the displayed part of your view, in pixels.
13179     */
13180    public final int getScrollX() {
13181        return mScrollX;
13182    }
13183
13184    /**
13185     * Return the scrolled top position of this view. This is the top edge of
13186     * the displayed part of your view. You do not need to draw any pixels above
13187     * it, since those are outside of the frame of your view on screen.
13188     *
13189     * @return The top edge of the displayed part of your view, in pixels.
13190     */
13191    public final int getScrollY() {
13192        return mScrollY;
13193    }
13194
13195    /**
13196     * Return the width of the your view.
13197     *
13198     * @return The width of your view, in pixels.
13199     */
13200    @ViewDebug.ExportedProperty(category = "layout")
13201    public final int getWidth() {
13202        return mRight - mLeft;
13203    }
13204
13205    /**
13206     * Return the height of your view.
13207     *
13208     * @return The height of your view, in pixels.
13209     */
13210    @ViewDebug.ExportedProperty(category = "layout")
13211    public final int getHeight() {
13212        return mBottom - mTop;
13213    }
13214
13215    /**
13216     * Return the visible drawing bounds of your view. Fills in the output
13217     * rectangle with the values from getScrollX(), getScrollY(),
13218     * getWidth(), and getHeight(). These bounds do not account for any
13219     * transformation properties currently set on the view, such as
13220     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13221     *
13222     * @param outRect The (scrolled) drawing bounds of the view.
13223     */
13224    public void getDrawingRect(Rect outRect) {
13225        outRect.left = mScrollX;
13226        outRect.top = mScrollY;
13227        outRect.right = mScrollX + (mRight - mLeft);
13228        outRect.bottom = mScrollY + (mBottom - mTop);
13229    }
13230
13231    /**
13232     * Like {@link #getMeasuredWidthAndState()}, but only returns the
13233     * raw width component (that is the result is masked by
13234     * {@link #MEASURED_SIZE_MASK}).
13235     *
13236     * @return The raw measured width of this view.
13237     */
13238    public final int getMeasuredWidth() {
13239        return mMeasuredWidth & MEASURED_SIZE_MASK;
13240    }
13241
13242    /**
13243     * Return the full width measurement information for this view as computed
13244     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13245     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13246     * This should be used during measurement and layout calculations only. Use
13247     * {@link #getWidth()} to see how wide a view is after layout.
13248     *
13249     * @return The measured width of this view as a bit mask.
13250     */
13251    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13252            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13253                    name = "MEASURED_STATE_TOO_SMALL"),
13254    })
13255    public final int getMeasuredWidthAndState() {
13256        return mMeasuredWidth;
13257    }
13258
13259    /**
13260     * Like {@link #getMeasuredHeightAndState()}, but only returns the
13261     * raw height component (that is the result is masked by
13262     * {@link #MEASURED_SIZE_MASK}).
13263     *
13264     * @return The raw measured height of this view.
13265     */
13266    public final int getMeasuredHeight() {
13267        return mMeasuredHeight & MEASURED_SIZE_MASK;
13268    }
13269
13270    /**
13271     * Return the full height measurement information for this view as computed
13272     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13273     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13274     * This should be used during measurement and layout calculations only. Use
13275     * {@link #getHeight()} to see how wide a view is after layout.
13276     *
13277     * @return The measured height of this view as a bit mask.
13278     */
13279    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13280            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13281                    name = "MEASURED_STATE_TOO_SMALL"),
13282    })
13283    public final int getMeasuredHeightAndState() {
13284        return mMeasuredHeight;
13285    }
13286
13287    /**
13288     * Return only the state bits of {@link #getMeasuredWidthAndState()}
13289     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13290     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13291     * and the height component is at the shifted bits
13292     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13293     */
13294    public final int getMeasuredState() {
13295        return (mMeasuredWidth&MEASURED_STATE_MASK)
13296                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13297                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13298    }
13299
13300    /**
13301     * The transform matrix of this view, which is calculated based on the current
13302     * rotation, scale, and pivot properties.
13303     *
13304     * @see #getRotation()
13305     * @see #getScaleX()
13306     * @see #getScaleY()
13307     * @see #getPivotX()
13308     * @see #getPivotY()
13309     * @return The current transform matrix for the view
13310     */
13311    public Matrix getMatrix() {
13312        ensureTransformationInfo();
13313        final Matrix matrix = mTransformationInfo.mMatrix;
13314        mRenderNode.getMatrix(matrix);
13315        return matrix;
13316    }
13317
13318    /**
13319     * Returns true if the transform matrix is the identity matrix.
13320     * Recomputes the matrix if necessary.
13321     *
13322     * @return True if the transform matrix is the identity matrix, false otherwise.
13323     */
13324    final boolean hasIdentityMatrix() {
13325        return mRenderNode.hasIdentityMatrix();
13326    }
13327
13328    void ensureTransformationInfo() {
13329        if (mTransformationInfo == null) {
13330            mTransformationInfo = new TransformationInfo();
13331        }
13332    }
13333
13334    /**
13335     * Utility method to retrieve the inverse of the current mMatrix property.
13336     * We cache the matrix to avoid recalculating it when transform properties
13337     * have not changed.
13338     *
13339     * @return The inverse of the current matrix of this view.
13340     * @hide
13341     */
13342    public final Matrix getInverseMatrix() {
13343        ensureTransformationInfo();
13344        if (mTransformationInfo.mInverseMatrix == null) {
13345            mTransformationInfo.mInverseMatrix = new Matrix();
13346        }
13347        final Matrix matrix = mTransformationInfo.mInverseMatrix;
13348        mRenderNode.getInverseMatrix(matrix);
13349        return matrix;
13350    }
13351
13352    /**
13353     * Gets the distance along the Z axis from the camera to this view.
13354     *
13355     * @see #setCameraDistance(float)
13356     *
13357     * @return The distance along the Z axis.
13358     */
13359    public float getCameraDistance() {
13360        final float dpi = mResources.getDisplayMetrics().densityDpi;
13361        return -(mRenderNode.getCameraDistance() * dpi);
13362    }
13363
13364    /**
13365     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13366     * views are drawn) from the camera to this view. The camera's distance
13367     * affects 3D transformations, for instance rotations around the X and Y
13368     * axis. If the rotationX or rotationY properties are changed and this view is
13369     * large (more than half the size of the screen), it is recommended to always
13370     * use a camera distance that's greater than the height (X axis rotation) or
13371     * the width (Y axis rotation) of this view.</p>
13372     *
13373     * <p>The distance of the camera from the view plane can have an affect on the
13374     * perspective distortion of the view when it is rotated around the x or y axis.
13375     * For example, a large distance will result in a large viewing angle, and there
13376     * will not be much perspective distortion of the view as it rotates. A short
13377     * distance may cause much more perspective distortion upon rotation, and can
13378     * also result in some drawing artifacts if the rotated view ends up partially
13379     * behind the camera (which is why the recommendation is to use a distance at
13380     * least as far as the size of the view, if the view is to be rotated.)</p>
13381     *
13382     * <p>The distance is expressed in "depth pixels." The default distance depends
13383     * on the screen density. For instance, on a medium density display, the
13384     * default distance is 1280. On a high density display, the default distance
13385     * is 1920.</p>
13386     *
13387     * <p>If you want to specify a distance that leads to visually consistent
13388     * results across various densities, use the following formula:</p>
13389     * <pre>
13390     * float scale = context.getResources().getDisplayMetrics().density;
13391     * view.setCameraDistance(distance * scale);
13392     * </pre>
13393     *
13394     * <p>The density scale factor of a high density display is 1.5,
13395     * and 1920 = 1280 * 1.5.</p>
13396     *
13397     * @param distance The distance in "depth pixels", if negative the opposite
13398     *        value is used
13399     *
13400     * @see #setRotationX(float)
13401     * @see #setRotationY(float)
13402     */
13403    public void setCameraDistance(float distance) {
13404        final float dpi = mResources.getDisplayMetrics().densityDpi;
13405
13406        invalidateViewProperty(true, false);
13407        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13408        invalidateViewProperty(false, false);
13409
13410        invalidateParentIfNeededAndWasQuickRejected();
13411    }
13412
13413    /**
13414     * The degrees that the view is rotated around the pivot point.
13415     *
13416     * @see #setRotation(float)
13417     * @see #getPivotX()
13418     * @see #getPivotY()
13419     *
13420     * @return The degrees of rotation.
13421     */
13422    @ViewDebug.ExportedProperty(category = "drawing")
13423    public float getRotation() {
13424        return mRenderNode.getRotation();
13425    }
13426
13427    /**
13428     * Sets the degrees that the view is rotated around the pivot point. Increasing values
13429     * result in clockwise rotation.
13430     *
13431     * @param rotation The degrees of rotation.
13432     *
13433     * @see #getRotation()
13434     * @see #getPivotX()
13435     * @see #getPivotY()
13436     * @see #setRotationX(float)
13437     * @see #setRotationY(float)
13438     *
13439     * @attr ref android.R.styleable#View_rotation
13440     */
13441    public void setRotation(float rotation) {
13442        if (rotation != getRotation()) {
13443            // Double-invalidation is necessary to capture view's old and new areas
13444            invalidateViewProperty(true, false);
13445            mRenderNode.setRotation(rotation);
13446            invalidateViewProperty(false, true);
13447
13448            invalidateParentIfNeededAndWasQuickRejected();
13449            notifySubtreeAccessibilityStateChangedIfNeeded();
13450        }
13451    }
13452
13453    /**
13454     * The degrees that the view is rotated around the vertical axis through the pivot point.
13455     *
13456     * @see #getPivotX()
13457     * @see #getPivotY()
13458     * @see #setRotationY(float)
13459     *
13460     * @return The degrees of Y rotation.
13461     */
13462    @ViewDebug.ExportedProperty(category = "drawing")
13463    public float getRotationY() {
13464        return mRenderNode.getRotationY();
13465    }
13466
13467    /**
13468     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13469     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13470     * down the y axis.
13471     *
13472     * When rotating large views, it is recommended to adjust the camera distance
13473     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13474     *
13475     * @param rotationY The degrees of Y rotation.
13476     *
13477     * @see #getRotationY()
13478     * @see #getPivotX()
13479     * @see #getPivotY()
13480     * @see #setRotation(float)
13481     * @see #setRotationX(float)
13482     * @see #setCameraDistance(float)
13483     *
13484     * @attr ref android.R.styleable#View_rotationY
13485     */
13486    public void setRotationY(float rotationY) {
13487        if (rotationY != getRotationY()) {
13488            invalidateViewProperty(true, false);
13489            mRenderNode.setRotationY(rotationY);
13490            invalidateViewProperty(false, true);
13491
13492            invalidateParentIfNeededAndWasQuickRejected();
13493            notifySubtreeAccessibilityStateChangedIfNeeded();
13494        }
13495    }
13496
13497    /**
13498     * The degrees that the view is rotated around the horizontal axis through the pivot point.
13499     *
13500     * @see #getPivotX()
13501     * @see #getPivotY()
13502     * @see #setRotationX(float)
13503     *
13504     * @return The degrees of X rotation.
13505     */
13506    @ViewDebug.ExportedProperty(category = "drawing")
13507    public float getRotationX() {
13508        return mRenderNode.getRotationX();
13509    }
13510
13511    /**
13512     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13513     * Increasing values result in clockwise rotation from the viewpoint of looking down the
13514     * x axis.
13515     *
13516     * When rotating large views, it is recommended to adjust the camera distance
13517     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13518     *
13519     * @param rotationX The degrees of X rotation.
13520     *
13521     * @see #getRotationX()
13522     * @see #getPivotX()
13523     * @see #getPivotY()
13524     * @see #setRotation(float)
13525     * @see #setRotationY(float)
13526     * @see #setCameraDistance(float)
13527     *
13528     * @attr ref android.R.styleable#View_rotationX
13529     */
13530    public void setRotationX(float rotationX) {
13531        if (rotationX != getRotationX()) {
13532            invalidateViewProperty(true, false);
13533            mRenderNode.setRotationX(rotationX);
13534            invalidateViewProperty(false, true);
13535
13536            invalidateParentIfNeededAndWasQuickRejected();
13537            notifySubtreeAccessibilityStateChangedIfNeeded();
13538        }
13539    }
13540
13541    /**
13542     * The amount that the view is scaled in x around the pivot point, as a proportion of
13543     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
13544     *
13545     * <p>By default, this is 1.0f.
13546     *
13547     * @see #getPivotX()
13548     * @see #getPivotY()
13549     * @return The scaling factor.
13550     */
13551    @ViewDebug.ExportedProperty(category = "drawing")
13552    public float getScaleX() {
13553        return mRenderNode.getScaleX();
13554    }
13555
13556    /**
13557     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
13558     * the view's unscaled width. A value of 1 means that no scaling is applied.
13559     *
13560     * @param scaleX The scaling factor.
13561     * @see #getPivotX()
13562     * @see #getPivotY()
13563     *
13564     * @attr ref android.R.styleable#View_scaleX
13565     */
13566    public void setScaleX(float scaleX) {
13567        if (scaleX != getScaleX()) {
13568            invalidateViewProperty(true, false);
13569            mRenderNode.setScaleX(scaleX);
13570            invalidateViewProperty(false, true);
13571
13572            invalidateParentIfNeededAndWasQuickRejected();
13573            notifySubtreeAccessibilityStateChangedIfNeeded();
13574        }
13575    }
13576
13577    /**
13578     * The amount that the view is scaled in y around the pivot point, as a proportion of
13579     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
13580     *
13581     * <p>By default, this is 1.0f.
13582     *
13583     * @see #getPivotX()
13584     * @see #getPivotY()
13585     * @return The scaling factor.
13586     */
13587    @ViewDebug.ExportedProperty(category = "drawing")
13588    public float getScaleY() {
13589        return mRenderNode.getScaleY();
13590    }
13591
13592    /**
13593     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
13594     * the view's unscaled width. A value of 1 means that no scaling is applied.
13595     *
13596     * @param scaleY The scaling factor.
13597     * @see #getPivotX()
13598     * @see #getPivotY()
13599     *
13600     * @attr ref android.R.styleable#View_scaleY
13601     */
13602    public void setScaleY(float scaleY) {
13603        if (scaleY != getScaleY()) {
13604            invalidateViewProperty(true, false);
13605            mRenderNode.setScaleY(scaleY);
13606            invalidateViewProperty(false, true);
13607
13608            invalidateParentIfNeededAndWasQuickRejected();
13609            notifySubtreeAccessibilityStateChangedIfNeeded();
13610        }
13611    }
13612
13613    /**
13614     * The x location of the point around which the view is {@link #setRotation(float) rotated}
13615     * and {@link #setScaleX(float) scaled}.
13616     *
13617     * @see #getRotation()
13618     * @see #getScaleX()
13619     * @see #getScaleY()
13620     * @see #getPivotY()
13621     * @return The x location of the pivot point.
13622     *
13623     * @attr ref android.R.styleable#View_transformPivotX
13624     */
13625    @ViewDebug.ExportedProperty(category = "drawing")
13626    public float getPivotX() {
13627        return mRenderNode.getPivotX();
13628    }
13629
13630    /**
13631     * Sets the x location of the point around which the view is
13632     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
13633     * By default, the pivot point is centered on the object.
13634     * Setting this property disables this behavior and causes the view to use only the
13635     * explicitly set pivotX and pivotY values.
13636     *
13637     * @param pivotX The x location of the pivot point.
13638     * @see #getRotation()
13639     * @see #getScaleX()
13640     * @see #getScaleY()
13641     * @see #getPivotY()
13642     *
13643     * @attr ref android.R.styleable#View_transformPivotX
13644     */
13645    public void setPivotX(float pivotX) {
13646        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
13647            invalidateViewProperty(true, false);
13648            mRenderNode.setPivotX(pivotX);
13649            invalidateViewProperty(false, true);
13650
13651            invalidateParentIfNeededAndWasQuickRejected();
13652        }
13653    }
13654
13655    /**
13656     * The y location of the point around which the view is {@link #setRotation(float) rotated}
13657     * and {@link #setScaleY(float) scaled}.
13658     *
13659     * @see #getRotation()
13660     * @see #getScaleX()
13661     * @see #getScaleY()
13662     * @see #getPivotY()
13663     * @return The y location of the pivot point.
13664     *
13665     * @attr ref android.R.styleable#View_transformPivotY
13666     */
13667    @ViewDebug.ExportedProperty(category = "drawing")
13668    public float getPivotY() {
13669        return mRenderNode.getPivotY();
13670    }
13671
13672    /**
13673     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
13674     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
13675     * Setting this property disables this behavior and causes the view to use only the
13676     * explicitly set pivotX and pivotY values.
13677     *
13678     * @param pivotY The y location of the pivot point.
13679     * @see #getRotation()
13680     * @see #getScaleX()
13681     * @see #getScaleY()
13682     * @see #getPivotY()
13683     *
13684     * @attr ref android.R.styleable#View_transformPivotY
13685     */
13686    public void setPivotY(float pivotY) {
13687        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
13688            invalidateViewProperty(true, false);
13689            mRenderNode.setPivotY(pivotY);
13690            invalidateViewProperty(false, true);
13691
13692            invalidateParentIfNeededAndWasQuickRejected();
13693        }
13694    }
13695
13696    /**
13697     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
13698     * completely transparent and 1 means the view is completely opaque.
13699     *
13700     * <p>By default this is 1.0f.
13701     * @return The opacity of the view.
13702     */
13703    @ViewDebug.ExportedProperty(category = "drawing")
13704    public float getAlpha() {
13705        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
13706    }
13707
13708    /**
13709     * Sets the behavior for overlapping rendering for this view (see {@link
13710     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
13711     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
13712     * providing the value which is then used internally. That is, when {@link
13713     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
13714     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
13715     * instead.
13716     *
13717     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
13718     * instead of that returned by {@link #hasOverlappingRendering()}.
13719     *
13720     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
13721     */
13722    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
13723        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
13724        if (hasOverlappingRendering) {
13725            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13726        } else {
13727            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
13728        }
13729    }
13730
13731    /**
13732     * Returns the value for overlapping rendering that is used internally. This is either
13733     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
13734     * the return value of {@link #hasOverlappingRendering()}, otherwise.
13735     *
13736     * @return The value for overlapping rendering being used internally.
13737     */
13738    public final boolean getHasOverlappingRendering() {
13739        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
13740                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
13741                hasOverlappingRendering();
13742    }
13743
13744    /**
13745     * Returns whether this View has content which overlaps.
13746     *
13747     * <p>This function, intended to be overridden by specific View types, is an optimization when
13748     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
13749     * an offscreen buffer and then composited into place, which can be expensive. If the view has
13750     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
13751     * directly. An example of overlapping rendering is a TextView with a background image, such as
13752     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
13753     * ImageView with only the foreground image. The default implementation returns true; subclasses
13754     * should override if they have cases which can be optimized.</p>
13755     *
13756     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
13757     * necessitates that a View return true if it uses the methods internally without passing the
13758     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
13759     *
13760     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
13761     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
13762     *
13763     * @return true if the content in this view might overlap, false otherwise.
13764     */
13765    @ViewDebug.ExportedProperty(category = "drawing")
13766    public boolean hasOverlappingRendering() {
13767        return true;
13768    }
13769
13770    /**
13771     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
13772     * completely transparent and 1 means the view is completely opaque.
13773     *
13774     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
13775     * can have significant performance implications, especially for large views. It is best to use
13776     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
13777     *
13778     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
13779     * strongly recommended for performance reasons to either override
13780     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
13781     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
13782     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
13783     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
13784     * of rendering cost, even for simple or small views. Starting with
13785     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
13786     * applied to the view at the rendering level.</p>
13787     *
13788     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
13789     * responsible for applying the opacity itself.</p>
13790     *
13791     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
13792     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
13793     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
13794     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
13795     *
13796     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
13797     * value will clip a View to its bounds, unless the View returns <code>false</code> from
13798     * {@link #hasOverlappingRendering}.</p>
13799     *
13800     * @param alpha The opacity of the view.
13801     *
13802     * @see #hasOverlappingRendering()
13803     * @see #setLayerType(int, android.graphics.Paint)
13804     *
13805     * @attr ref android.R.styleable#View_alpha
13806     */
13807    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
13808        ensureTransformationInfo();
13809        if (mTransformationInfo.mAlpha != alpha) {
13810            // Report visibility changes, which can affect children, to accessibility
13811            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
13812                notifySubtreeAccessibilityStateChangedIfNeeded();
13813            }
13814            mTransformationInfo.mAlpha = alpha;
13815            if (onSetAlpha((int) (alpha * 255))) {
13816                mPrivateFlags |= PFLAG_ALPHA_SET;
13817                // subclass is handling alpha - don't optimize rendering cache invalidation
13818                invalidateParentCaches();
13819                invalidate(true);
13820            } else {
13821                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13822                invalidateViewProperty(true, false);
13823                mRenderNode.setAlpha(getFinalAlpha());
13824            }
13825        }
13826    }
13827
13828    /**
13829     * Faster version of setAlpha() which performs the same steps except there are
13830     * no calls to invalidate(). The caller of this function should perform proper invalidation
13831     * on the parent and this object. The return value indicates whether the subclass handles
13832     * alpha (the return value for onSetAlpha()).
13833     *
13834     * @param alpha The new value for the alpha property
13835     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
13836     *         the new value for the alpha property is different from the old value
13837     */
13838    boolean setAlphaNoInvalidation(float alpha) {
13839        ensureTransformationInfo();
13840        if (mTransformationInfo.mAlpha != alpha) {
13841            mTransformationInfo.mAlpha = alpha;
13842            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
13843            if (subclassHandlesAlpha) {
13844                mPrivateFlags |= PFLAG_ALPHA_SET;
13845                return true;
13846            } else {
13847                mPrivateFlags &= ~PFLAG_ALPHA_SET;
13848                mRenderNode.setAlpha(getFinalAlpha());
13849            }
13850        }
13851        return false;
13852    }
13853
13854    /**
13855     * This property is hidden and intended only for use by the Fade transition, which
13856     * animates it to produce a visual translucency that does not side-effect (or get
13857     * affected by) the real alpha property. This value is composited with the other
13858     * alpha value (and the AlphaAnimation value, when that is present) to produce
13859     * a final visual translucency result, which is what is passed into the DisplayList.
13860     *
13861     * @hide
13862     */
13863    public void setTransitionAlpha(float alpha) {
13864        ensureTransformationInfo();
13865        if (mTransformationInfo.mTransitionAlpha != alpha) {
13866            mTransformationInfo.mTransitionAlpha = alpha;
13867            mPrivateFlags &= ~PFLAG_ALPHA_SET;
13868            invalidateViewProperty(true, false);
13869            mRenderNode.setAlpha(getFinalAlpha());
13870        }
13871    }
13872
13873    /**
13874     * Calculates the visual alpha of this view, which is a combination of the actual
13875     * alpha value and the transitionAlpha value (if set).
13876     */
13877    private float getFinalAlpha() {
13878        if (mTransformationInfo != null) {
13879            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
13880        }
13881        return 1;
13882    }
13883
13884    /**
13885     * This property is hidden and intended only for use by the Fade transition, which
13886     * animates it to produce a visual translucency that does not side-effect (or get
13887     * affected by) the real alpha property. This value is composited with the other
13888     * alpha value (and the AlphaAnimation value, when that is present) to produce
13889     * a final visual translucency result, which is what is passed into the DisplayList.
13890     *
13891     * @hide
13892     */
13893    @ViewDebug.ExportedProperty(category = "drawing")
13894    public float getTransitionAlpha() {
13895        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
13896    }
13897
13898    /**
13899     * Top position of this view relative to its parent.
13900     *
13901     * @return The top of this view, in pixels.
13902     */
13903    @ViewDebug.CapturedViewProperty
13904    public final int getTop() {
13905        return mTop;
13906    }
13907
13908    /**
13909     * Sets the top position of this view relative to its parent. This method is meant to be called
13910     * by the layout system and should not generally be called otherwise, because the property
13911     * may be changed at any time by the layout.
13912     *
13913     * @param top The top of this view, in pixels.
13914     */
13915    public final void setTop(int top) {
13916        if (top != mTop) {
13917            final boolean matrixIsIdentity = hasIdentityMatrix();
13918            if (matrixIsIdentity) {
13919                if (mAttachInfo != null) {
13920                    int minTop;
13921                    int yLoc;
13922                    if (top < mTop) {
13923                        minTop = top;
13924                        yLoc = top - mTop;
13925                    } else {
13926                        minTop = mTop;
13927                        yLoc = 0;
13928                    }
13929                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
13930                }
13931            } else {
13932                // Double-invalidation is necessary to capture view's old and new areas
13933                invalidate(true);
13934            }
13935
13936            int width = mRight - mLeft;
13937            int oldHeight = mBottom - mTop;
13938
13939            mTop = top;
13940            mRenderNode.setTop(mTop);
13941
13942            sizeChange(width, mBottom - mTop, width, oldHeight);
13943
13944            if (!matrixIsIdentity) {
13945                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13946                invalidate(true);
13947            }
13948            mBackgroundSizeChanged = true;
13949            mDefaultFocusHighlightSizeChanged = true;
13950            if (mForegroundInfo != null) {
13951                mForegroundInfo.mBoundsChanged = true;
13952            }
13953            invalidateParentIfNeeded();
13954            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
13955                // View was rejected last time it was drawn by its parent; this may have changed
13956                invalidateParentIfNeeded();
13957            }
13958        }
13959    }
13960
13961    /**
13962     * Bottom position of this view relative to its parent.
13963     *
13964     * @return The bottom of this view, in pixels.
13965     */
13966    @ViewDebug.CapturedViewProperty
13967    public final int getBottom() {
13968        return mBottom;
13969    }
13970
13971    /**
13972     * True if this view has changed since the last time being drawn.
13973     *
13974     * @return The dirty state of this view.
13975     */
13976    public boolean isDirty() {
13977        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
13978    }
13979
13980    /**
13981     * Sets the bottom position of this view relative to its parent. This method is meant to be
13982     * called by the layout system and should not generally be called otherwise, because the
13983     * property may be changed at any time by the layout.
13984     *
13985     * @param bottom The bottom of this view, in pixels.
13986     */
13987    public final void setBottom(int bottom) {
13988        if (bottom != mBottom) {
13989            final boolean matrixIsIdentity = hasIdentityMatrix();
13990            if (matrixIsIdentity) {
13991                if (mAttachInfo != null) {
13992                    int maxBottom;
13993                    if (bottom < mBottom) {
13994                        maxBottom = mBottom;
13995                    } else {
13996                        maxBottom = bottom;
13997                    }
13998                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
13999                }
14000            } else {
14001                // Double-invalidation is necessary to capture view's old and new areas
14002                invalidate(true);
14003            }
14004
14005            int width = mRight - mLeft;
14006            int oldHeight = mBottom - mTop;
14007
14008            mBottom = bottom;
14009            mRenderNode.setBottom(mBottom);
14010
14011            sizeChange(width, mBottom - mTop, width, oldHeight);
14012
14013            if (!matrixIsIdentity) {
14014                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14015                invalidate(true);
14016            }
14017            mBackgroundSizeChanged = true;
14018            mDefaultFocusHighlightSizeChanged = true;
14019            if (mForegroundInfo != null) {
14020                mForegroundInfo.mBoundsChanged = true;
14021            }
14022            invalidateParentIfNeeded();
14023            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14024                // View was rejected last time it was drawn by its parent; this may have changed
14025                invalidateParentIfNeeded();
14026            }
14027        }
14028    }
14029
14030    /**
14031     * Left position of this view relative to its parent.
14032     *
14033     * @return The left edge of this view, in pixels.
14034     */
14035    @ViewDebug.CapturedViewProperty
14036    public final int getLeft() {
14037        return mLeft;
14038    }
14039
14040    /**
14041     * Sets the left position of this view relative to its parent. This method is meant to be called
14042     * by the layout system and should not generally be called otherwise, because the property
14043     * may be changed at any time by the layout.
14044     *
14045     * @param left The left of this view, in pixels.
14046     */
14047    public final void setLeft(int left) {
14048        if (left != mLeft) {
14049            final boolean matrixIsIdentity = hasIdentityMatrix();
14050            if (matrixIsIdentity) {
14051                if (mAttachInfo != null) {
14052                    int minLeft;
14053                    int xLoc;
14054                    if (left < mLeft) {
14055                        minLeft = left;
14056                        xLoc = left - mLeft;
14057                    } else {
14058                        minLeft = mLeft;
14059                        xLoc = 0;
14060                    }
14061                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
14062                }
14063            } else {
14064                // Double-invalidation is necessary to capture view's old and new areas
14065                invalidate(true);
14066            }
14067
14068            int oldWidth = mRight - mLeft;
14069            int height = mBottom - mTop;
14070
14071            mLeft = left;
14072            mRenderNode.setLeft(left);
14073
14074            sizeChange(mRight - mLeft, height, oldWidth, height);
14075
14076            if (!matrixIsIdentity) {
14077                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14078                invalidate(true);
14079            }
14080            mBackgroundSizeChanged = true;
14081            mDefaultFocusHighlightSizeChanged = true;
14082            if (mForegroundInfo != null) {
14083                mForegroundInfo.mBoundsChanged = true;
14084            }
14085            invalidateParentIfNeeded();
14086            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14087                // View was rejected last time it was drawn by its parent; this may have changed
14088                invalidateParentIfNeeded();
14089            }
14090        }
14091    }
14092
14093    /**
14094     * Right position of this view relative to its parent.
14095     *
14096     * @return The right edge of this view, in pixels.
14097     */
14098    @ViewDebug.CapturedViewProperty
14099    public final int getRight() {
14100        return mRight;
14101    }
14102
14103    /**
14104     * Sets the right position of this view relative to its parent. This method is meant to be called
14105     * by the layout system and should not generally be called otherwise, because the property
14106     * may be changed at any time by the layout.
14107     *
14108     * @param right The right of this view, in pixels.
14109     */
14110    public final void setRight(int right) {
14111        if (right != mRight) {
14112            final boolean matrixIsIdentity = hasIdentityMatrix();
14113            if (matrixIsIdentity) {
14114                if (mAttachInfo != null) {
14115                    int maxRight;
14116                    if (right < mRight) {
14117                        maxRight = mRight;
14118                    } else {
14119                        maxRight = right;
14120                    }
14121                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14122                }
14123            } else {
14124                // Double-invalidation is necessary to capture view's old and new areas
14125                invalidate(true);
14126            }
14127
14128            int oldWidth = mRight - mLeft;
14129            int height = mBottom - mTop;
14130
14131            mRight = right;
14132            mRenderNode.setRight(mRight);
14133
14134            sizeChange(mRight - mLeft, height, oldWidth, height);
14135
14136            if (!matrixIsIdentity) {
14137                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14138                invalidate(true);
14139            }
14140            mBackgroundSizeChanged = true;
14141            mDefaultFocusHighlightSizeChanged = true;
14142            if (mForegroundInfo != null) {
14143                mForegroundInfo.mBoundsChanged = true;
14144            }
14145            invalidateParentIfNeeded();
14146            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14147                // View was rejected last time it was drawn by its parent; this may have changed
14148                invalidateParentIfNeeded();
14149            }
14150        }
14151    }
14152
14153    /**
14154     * The visual x position of this view, in pixels. This is equivalent to the
14155     * {@link #setTranslationX(float) translationX} property plus the current
14156     * {@link #getLeft() left} property.
14157     *
14158     * @return The visual x position of this view, in pixels.
14159     */
14160    @ViewDebug.ExportedProperty(category = "drawing")
14161    public float getX() {
14162        return mLeft + getTranslationX();
14163    }
14164
14165    /**
14166     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14167     * {@link #setTranslationX(float) translationX} property to be the difference between
14168     * the x value passed in and the current {@link #getLeft() left} property.
14169     *
14170     * @param x The visual x position of this view, in pixels.
14171     */
14172    public void setX(float x) {
14173        setTranslationX(x - mLeft);
14174    }
14175
14176    /**
14177     * The visual y position of this view, in pixels. This is equivalent to the
14178     * {@link #setTranslationY(float) translationY} property plus the current
14179     * {@link #getTop() top} property.
14180     *
14181     * @return The visual y position of this view, in pixels.
14182     */
14183    @ViewDebug.ExportedProperty(category = "drawing")
14184    public float getY() {
14185        return mTop + getTranslationY();
14186    }
14187
14188    /**
14189     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14190     * {@link #setTranslationY(float) translationY} property to be the difference between
14191     * the y value passed in and the current {@link #getTop() top} property.
14192     *
14193     * @param y The visual y position of this view, in pixels.
14194     */
14195    public void setY(float y) {
14196        setTranslationY(y - mTop);
14197    }
14198
14199    /**
14200     * The visual z position of this view, in pixels. This is equivalent to the
14201     * {@link #setTranslationZ(float) translationZ} property plus the current
14202     * {@link #getElevation() elevation} property.
14203     *
14204     * @return The visual z position of this view, in pixels.
14205     */
14206    @ViewDebug.ExportedProperty(category = "drawing")
14207    public float getZ() {
14208        return getElevation() + getTranslationZ();
14209    }
14210
14211    /**
14212     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14213     * {@link #setTranslationZ(float) translationZ} property to be the difference between
14214     * the x value passed in and the current {@link #getElevation() elevation} property.
14215     *
14216     * @param z The visual z position of this view, in pixels.
14217     */
14218    public void setZ(float z) {
14219        setTranslationZ(z - getElevation());
14220    }
14221
14222    /**
14223     * The base elevation of this view relative to its parent, in pixels.
14224     *
14225     * @return The base depth position of the view, in pixels.
14226     */
14227    @ViewDebug.ExportedProperty(category = "drawing")
14228    public float getElevation() {
14229        return mRenderNode.getElevation();
14230    }
14231
14232    /**
14233     * Sets the base elevation of this view, in pixels.
14234     *
14235     * @attr ref android.R.styleable#View_elevation
14236     */
14237    public void setElevation(float elevation) {
14238        if (elevation != getElevation()) {
14239            invalidateViewProperty(true, false);
14240            mRenderNode.setElevation(elevation);
14241            invalidateViewProperty(false, true);
14242
14243            invalidateParentIfNeededAndWasQuickRejected();
14244        }
14245    }
14246
14247    /**
14248     * The horizontal location of this view relative to its {@link #getLeft() left} position.
14249     * This position is post-layout, in addition to wherever the object's
14250     * layout placed it.
14251     *
14252     * @return The horizontal position of this view relative to its left position, in pixels.
14253     */
14254    @ViewDebug.ExportedProperty(category = "drawing")
14255    public float getTranslationX() {
14256        return mRenderNode.getTranslationX();
14257    }
14258
14259    /**
14260     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14261     * This effectively positions the object post-layout, in addition to wherever the object's
14262     * layout placed it.
14263     *
14264     * @param translationX The horizontal position of this view relative to its left position,
14265     * in pixels.
14266     *
14267     * @attr ref android.R.styleable#View_translationX
14268     */
14269    public void setTranslationX(float translationX) {
14270        if (translationX != getTranslationX()) {
14271            invalidateViewProperty(true, false);
14272            mRenderNode.setTranslationX(translationX);
14273            invalidateViewProperty(false, true);
14274
14275            invalidateParentIfNeededAndWasQuickRejected();
14276            notifySubtreeAccessibilityStateChangedIfNeeded();
14277        }
14278    }
14279
14280    /**
14281     * The vertical location of this view relative to its {@link #getTop() top} position.
14282     * This position is post-layout, in addition to wherever the object's
14283     * layout placed it.
14284     *
14285     * @return The vertical position of this view relative to its top position,
14286     * in pixels.
14287     */
14288    @ViewDebug.ExportedProperty(category = "drawing")
14289    public float getTranslationY() {
14290        return mRenderNode.getTranslationY();
14291    }
14292
14293    /**
14294     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14295     * This effectively positions the object post-layout, in addition to wherever the object's
14296     * layout placed it.
14297     *
14298     * @param translationY The vertical position of this view relative to its top position,
14299     * in pixels.
14300     *
14301     * @attr ref android.R.styleable#View_translationY
14302     */
14303    public void setTranslationY(float translationY) {
14304        if (translationY != getTranslationY()) {
14305            invalidateViewProperty(true, false);
14306            mRenderNode.setTranslationY(translationY);
14307            invalidateViewProperty(false, true);
14308
14309            invalidateParentIfNeededAndWasQuickRejected();
14310            notifySubtreeAccessibilityStateChangedIfNeeded();
14311        }
14312    }
14313
14314    /**
14315     * The depth location of this view relative to its {@link #getElevation() elevation}.
14316     *
14317     * @return The depth of this view relative to its elevation.
14318     */
14319    @ViewDebug.ExportedProperty(category = "drawing")
14320    public float getTranslationZ() {
14321        return mRenderNode.getTranslationZ();
14322    }
14323
14324    /**
14325     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14326     *
14327     * @attr ref android.R.styleable#View_translationZ
14328     */
14329    public void setTranslationZ(float translationZ) {
14330        if (translationZ != getTranslationZ()) {
14331            invalidateViewProperty(true, false);
14332            mRenderNode.setTranslationZ(translationZ);
14333            invalidateViewProperty(false, true);
14334
14335            invalidateParentIfNeededAndWasQuickRejected();
14336        }
14337    }
14338
14339    /** @hide */
14340    public void setAnimationMatrix(Matrix matrix) {
14341        invalidateViewProperty(true, false);
14342        mRenderNode.setAnimationMatrix(matrix);
14343        invalidateViewProperty(false, true);
14344
14345        invalidateParentIfNeededAndWasQuickRejected();
14346    }
14347
14348    /**
14349     * Returns the current StateListAnimator if exists.
14350     *
14351     * @return StateListAnimator or null if it does not exists
14352     * @see    #setStateListAnimator(android.animation.StateListAnimator)
14353     */
14354    public StateListAnimator getStateListAnimator() {
14355        return mStateListAnimator;
14356    }
14357
14358    /**
14359     * Attaches the provided StateListAnimator to this View.
14360     * <p>
14361     * Any previously attached StateListAnimator will be detached.
14362     *
14363     * @param stateListAnimator The StateListAnimator to update the view
14364     * @see android.animation.StateListAnimator
14365     */
14366    public void setStateListAnimator(StateListAnimator stateListAnimator) {
14367        if (mStateListAnimator == stateListAnimator) {
14368            return;
14369        }
14370        if (mStateListAnimator != null) {
14371            mStateListAnimator.setTarget(null);
14372        }
14373        mStateListAnimator = stateListAnimator;
14374        if (stateListAnimator != null) {
14375            stateListAnimator.setTarget(this);
14376            if (isAttachedToWindow()) {
14377                stateListAnimator.setState(getDrawableState());
14378            }
14379        }
14380    }
14381
14382    /**
14383     * Returns whether the Outline should be used to clip the contents of the View.
14384     * <p>
14385     * Note that this flag will only be respected if the View's Outline returns true from
14386     * {@link Outline#canClip()}.
14387     *
14388     * @see #setOutlineProvider(ViewOutlineProvider)
14389     * @see #setClipToOutline(boolean)
14390     */
14391    public final boolean getClipToOutline() {
14392        return mRenderNode.getClipToOutline();
14393    }
14394
14395    /**
14396     * Sets whether the View's Outline should be used to clip the contents of the View.
14397     * <p>
14398     * Only a single non-rectangular clip can be applied on a View at any time.
14399     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14400     * circular reveal} animation take priority over Outline clipping, and
14401     * child Outline clipping takes priority over Outline clipping done by a
14402     * parent.
14403     * <p>
14404     * Note that this flag will only be respected if the View's Outline returns true from
14405     * {@link Outline#canClip()}.
14406     *
14407     * @see #setOutlineProvider(ViewOutlineProvider)
14408     * @see #getClipToOutline()
14409     */
14410    public void setClipToOutline(boolean clipToOutline) {
14411        damageInParent();
14412        if (getClipToOutline() != clipToOutline) {
14413            mRenderNode.setClipToOutline(clipToOutline);
14414        }
14415    }
14416
14417    // correspond to the enum values of View_outlineProvider
14418    private static final int PROVIDER_BACKGROUND = 0;
14419    private static final int PROVIDER_NONE = 1;
14420    private static final int PROVIDER_BOUNDS = 2;
14421    private static final int PROVIDER_PADDED_BOUNDS = 3;
14422    private void setOutlineProviderFromAttribute(int providerInt) {
14423        switch (providerInt) {
14424            case PROVIDER_BACKGROUND:
14425                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14426                break;
14427            case PROVIDER_NONE:
14428                setOutlineProvider(null);
14429                break;
14430            case PROVIDER_BOUNDS:
14431                setOutlineProvider(ViewOutlineProvider.BOUNDS);
14432                break;
14433            case PROVIDER_PADDED_BOUNDS:
14434                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14435                break;
14436        }
14437    }
14438
14439    /**
14440     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14441     * the shape of the shadow it casts, and enables outline clipping.
14442     * <p>
14443     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14444     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14445     * outline provider with this method allows this behavior to be overridden.
14446     * <p>
14447     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14448     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14449     * <p>
14450     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14451     *
14452     * @see #setClipToOutline(boolean)
14453     * @see #getClipToOutline()
14454     * @see #getOutlineProvider()
14455     */
14456    public void setOutlineProvider(ViewOutlineProvider provider) {
14457        mOutlineProvider = provider;
14458        invalidateOutline();
14459    }
14460
14461    /**
14462     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14463     * that defines the shape of the shadow it casts, and enables outline clipping.
14464     *
14465     * @see #setOutlineProvider(ViewOutlineProvider)
14466     */
14467    public ViewOutlineProvider getOutlineProvider() {
14468        return mOutlineProvider;
14469    }
14470
14471    /**
14472     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14473     *
14474     * @see #setOutlineProvider(ViewOutlineProvider)
14475     */
14476    public void invalidateOutline() {
14477        rebuildOutline();
14478
14479        notifySubtreeAccessibilityStateChangedIfNeeded();
14480        invalidateViewProperty(false, false);
14481    }
14482
14483    /**
14484     * Internal version of {@link #invalidateOutline()} which invalidates the
14485     * outline without invalidating the view itself. This is intended to be called from
14486     * within methods in the View class itself which are the result of the view being
14487     * invalidated already. For example, when we are drawing the background of a View,
14488     * we invalidate the outline in case it changed in the meantime, but we do not
14489     * need to invalidate the view because we're already drawing the background as part
14490     * of drawing the view in response to an earlier invalidation of the view.
14491     */
14492    private void rebuildOutline() {
14493        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14494        if (mAttachInfo == null) return;
14495
14496        if (mOutlineProvider == null) {
14497            // no provider, remove outline
14498            mRenderNode.setOutline(null);
14499        } else {
14500            final Outline outline = mAttachInfo.mTmpOutline;
14501            outline.setEmpty();
14502            outline.setAlpha(1.0f);
14503
14504            mOutlineProvider.getOutline(this, outline);
14505            mRenderNode.setOutline(outline);
14506        }
14507    }
14508
14509    /**
14510     * HierarchyViewer only
14511     *
14512     * @hide
14513     */
14514    @ViewDebug.ExportedProperty(category = "drawing")
14515    public boolean hasShadow() {
14516        return mRenderNode.hasShadow();
14517    }
14518
14519
14520    /** @hide */
14521    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14522        mRenderNode.setRevealClip(shouldClip, x, y, radius);
14523        invalidateViewProperty(false, false);
14524    }
14525
14526    /**
14527     * Hit rectangle in parent's coordinates
14528     *
14529     * @param outRect The hit rectangle of the view.
14530     */
14531    public void getHitRect(Rect outRect) {
14532        if (hasIdentityMatrix() || mAttachInfo == null) {
14533            outRect.set(mLeft, mTop, mRight, mBottom);
14534        } else {
14535            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14536            tmpRect.set(0, 0, getWidth(), getHeight());
14537            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14538            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14539                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14540        }
14541    }
14542
14543    /**
14544     * Determines whether the given point, in local coordinates is inside the view.
14545     */
14546    /*package*/ final boolean pointInView(float localX, float localY) {
14547        return pointInView(localX, localY, 0);
14548    }
14549
14550    /**
14551     * Utility method to determine whether the given point, in local coordinates,
14552     * is inside the view, where the area of the view is expanded by the slop factor.
14553     * This method is called while processing touch-move events to determine if the event
14554     * is still within the view.
14555     *
14556     * @hide
14557     */
14558    public boolean pointInView(float localX, float localY, float slop) {
14559        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
14560                localY < ((mBottom - mTop) + slop);
14561    }
14562
14563    /**
14564     * When a view has focus and the user navigates away from it, the next view is searched for
14565     * starting from the rectangle filled in by this method.
14566     *
14567     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
14568     * of the view.  However, if your view maintains some idea of internal selection,
14569     * such as a cursor, or a selected row or column, you should override this method and
14570     * fill in a more specific rectangle.
14571     *
14572     * @param r The rectangle to fill in, in this view's coordinates.
14573     */
14574    public void getFocusedRect(Rect r) {
14575        getDrawingRect(r);
14576    }
14577
14578    /**
14579     * If some part of this view is not clipped by any of its parents, then
14580     * return that area in r in global (root) coordinates. To convert r to local
14581     * coordinates (without taking possible View rotations into account), offset
14582     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
14583     * If the view is completely clipped or translated out, return false.
14584     *
14585     * @param r If true is returned, r holds the global coordinates of the
14586     *        visible portion of this view.
14587     * @param globalOffset If true is returned, globalOffset holds the dx,dy
14588     *        between this view and its root. globalOffet may be null.
14589     * @return true if r is non-empty (i.e. part of the view is visible at the
14590     *         root level.
14591     */
14592    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
14593        int width = mRight - mLeft;
14594        int height = mBottom - mTop;
14595        if (width > 0 && height > 0) {
14596            r.set(0, 0, width, height);
14597            if (globalOffset != null) {
14598                globalOffset.set(-mScrollX, -mScrollY);
14599            }
14600            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
14601        }
14602        return false;
14603    }
14604
14605    public final boolean getGlobalVisibleRect(Rect r) {
14606        return getGlobalVisibleRect(r, null);
14607    }
14608
14609    public final boolean getLocalVisibleRect(Rect r) {
14610        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
14611        if (getGlobalVisibleRect(r, offset)) {
14612            r.offset(-offset.x, -offset.y); // make r local
14613            return true;
14614        }
14615        return false;
14616    }
14617
14618    /**
14619     * Offset this view's vertical location by the specified number of pixels.
14620     *
14621     * @param offset the number of pixels to offset the view by
14622     */
14623    public void offsetTopAndBottom(int offset) {
14624        if (offset != 0) {
14625            final boolean matrixIsIdentity = hasIdentityMatrix();
14626            if (matrixIsIdentity) {
14627                if (isHardwareAccelerated()) {
14628                    invalidateViewProperty(false, false);
14629                } else {
14630                    final ViewParent p = mParent;
14631                    if (p != null && mAttachInfo != null) {
14632                        final Rect r = mAttachInfo.mTmpInvalRect;
14633                        int minTop;
14634                        int maxBottom;
14635                        int yLoc;
14636                        if (offset < 0) {
14637                            minTop = mTop + offset;
14638                            maxBottom = mBottom;
14639                            yLoc = offset;
14640                        } else {
14641                            minTop = mTop;
14642                            maxBottom = mBottom + offset;
14643                            yLoc = 0;
14644                        }
14645                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
14646                        p.invalidateChild(this, r);
14647                    }
14648                }
14649            } else {
14650                invalidateViewProperty(false, false);
14651            }
14652
14653            mTop += offset;
14654            mBottom += offset;
14655            mRenderNode.offsetTopAndBottom(offset);
14656            if (isHardwareAccelerated()) {
14657                invalidateViewProperty(false, false);
14658                invalidateParentIfNeededAndWasQuickRejected();
14659            } else {
14660                if (!matrixIsIdentity) {
14661                    invalidateViewProperty(false, true);
14662                }
14663                invalidateParentIfNeeded();
14664            }
14665            notifySubtreeAccessibilityStateChangedIfNeeded();
14666        }
14667    }
14668
14669    /**
14670     * Offset this view's horizontal location by the specified amount of pixels.
14671     *
14672     * @param offset the number of pixels to offset the view by
14673     */
14674    public void offsetLeftAndRight(int offset) {
14675        if (offset != 0) {
14676            final boolean matrixIsIdentity = hasIdentityMatrix();
14677            if (matrixIsIdentity) {
14678                if (isHardwareAccelerated()) {
14679                    invalidateViewProperty(false, false);
14680                } else {
14681                    final ViewParent p = mParent;
14682                    if (p != null && mAttachInfo != null) {
14683                        final Rect r = mAttachInfo.mTmpInvalRect;
14684                        int minLeft;
14685                        int maxRight;
14686                        if (offset < 0) {
14687                            minLeft = mLeft + offset;
14688                            maxRight = mRight;
14689                        } else {
14690                            minLeft = mLeft;
14691                            maxRight = mRight + offset;
14692                        }
14693                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
14694                        p.invalidateChild(this, r);
14695                    }
14696                }
14697            } else {
14698                invalidateViewProperty(false, false);
14699            }
14700
14701            mLeft += offset;
14702            mRight += offset;
14703            mRenderNode.offsetLeftAndRight(offset);
14704            if (isHardwareAccelerated()) {
14705                invalidateViewProperty(false, false);
14706                invalidateParentIfNeededAndWasQuickRejected();
14707            } else {
14708                if (!matrixIsIdentity) {
14709                    invalidateViewProperty(false, true);
14710                }
14711                invalidateParentIfNeeded();
14712            }
14713            notifySubtreeAccessibilityStateChangedIfNeeded();
14714        }
14715    }
14716
14717    /**
14718     * Get the LayoutParams associated with this view. All views should have
14719     * layout parameters. These supply parameters to the <i>parent</i> of this
14720     * view specifying how it should be arranged. There are many subclasses of
14721     * ViewGroup.LayoutParams, and these correspond to the different subclasses
14722     * of ViewGroup that are responsible for arranging their children.
14723     *
14724     * This method may return null if this View is not attached to a parent
14725     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
14726     * was not invoked successfully. When a View is attached to a parent
14727     * ViewGroup, this method must not return null.
14728     *
14729     * @return The LayoutParams associated with this view, or null if no
14730     *         parameters have been set yet
14731     */
14732    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
14733    public ViewGroup.LayoutParams getLayoutParams() {
14734        return mLayoutParams;
14735    }
14736
14737    /**
14738     * Set the layout parameters associated with this view. These supply
14739     * parameters to the <i>parent</i> of this view specifying how it should be
14740     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
14741     * correspond to the different subclasses of ViewGroup that are responsible
14742     * for arranging their children.
14743     *
14744     * @param params The layout parameters for this view, cannot be null
14745     */
14746    public void setLayoutParams(ViewGroup.LayoutParams params) {
14747        if (params == null) {
14748            throw new NullPointerException("Layout parameters cannot be null");
14749        }
14750        mLayoutParams = params;
14751        resolveLayoutParams();
14752        if (mParent instanceof ViewGroup) {
14753            ((ViewGroup) mParent).onSetLayoutParams(this, params);
14754        }
14755        requestLayout();
14756    }
14757
14758    /**
14759     * Resolve the layout parameters depending on the resolved layout direction
14760     *
14761     * @hide
14762     */
14763    public void resolveLayoutParams() {
14764        if (mLayoutParams != null) {
14765            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
14766        }
14767    }
14768
14769    /**
14770     * Set the scrolled position of your view. This will cause a call to
14771     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14772     * invalidated.
14773     * @param x the x position to scroll to
14774     * @param y the y position to scroll to
14775     */
14776    public void scrollTo(int x, int y) {
14777        if (mScrollX != x || mScrollY != y) {
14778            int oldX = mScrollX;
14779            int oldY = mScrollY;
14780            mScrollX = x;
14781            mScrollY = y;
14782            invalidateParentCaches();
14783            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
14784            if (!awakenScrollBars()) {
14785                postInvalidateOnAnimation();
14786            }
14787        }
14788    }
14789
14790    /**
14791     * Move the scrolled position of your view. This will cause a call to
14792     * {@link #onScrollChanged(int, int, int, int)} and the view will be
14793     * invalidated.
14794     * @param x the amount of pixels to scroll by horizontally
14795     * @param y the amount of pixels to scroll by vertically
14796     */
14797    public void scrollBy(int x, int y) {
14798        scrollTo(mScrollX + x, mScrollY + y);
14799    }
14800
14801    /**
14802     * <p>Trigger the scrollbars to draw. When invoked this method starts an
14803     * animation to fade the scrollbars out after a default delay. If a subclass
14804     * provides animated scrolling, the start delay should equal the duration
14805     * of the scrolling animation.</p>
14806     *
14807     * <p>The animation starts only if at least one of the scrollbars is
14808     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
14809     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14810     * this method returns true, and false otherwise. If the animation is
14811     * started, this method calls {@link #invalidate()}; in that case the
14812     * caller should not call {@link #invalidate()}.</p>
14813     *
14814     * <p>This method should be invoked every time a subclass directly updates
14815     * the scroll parameters.</p>
14816     *
14817     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
14818     * and {@link #scrollTo(int, int)}.</p>
14819     *
14820     * @return true if the animation is played, false otherwise
14821     *
14822     * @see #awakenScrollBars(int)
14823     * @see #scrollBy(int, int)
14824     * @see #scrollTo(int, int)
14825     * @see #isHorizontalScrollBarEnabled()
14826     * @see #isVerticalScrollBarEnabled()
14827     * @see #setHorizontalScrollBarEnabled(boolean)
14828     * @see #setVerticalScrollBarEnabled(boolean)
14829     */
14830    protected boolean awakenScrollBars() {
14831        return mScrollCache != null &&
14832                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
14833    }
14834
14835    /**
14836     * Trigger the scrollbars to draw.
14837     * This method differs from awakenScrollBars() only in its default duration.
14838     * initialAwakenScrollBars() will show the scroll bars for longer than
14839     * usual to give the user more of a chance to notice them.
14840     *
14841     * @return true if the animation is played, false otherwise.
14842     */
14843    private boolean initialAwakenScrollBars() {
14844        return mScrollCache != null &&
14845                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
14846    }
14847
14848    /**
14849     * <p>
14850     * Trigger the scrollbars to draw. When invoked this method starts an
14851     * animation to fade the scrollbars out after a fixed delay. If a subclass
14852     * provides animated scrolling, the start delay should equal the duration of
14853     * the scrolling animation.
14854     * </p>
14855     *
14856     * <p>
14857     * The animation starts only if at least one of the scrollbars is enabled,
14858     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14859     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14860     * this method returns true, and false otherwise. If the animation is
14861     * started, this method calls {@link #invalidate()}; in that case the caller
14862     * should not call {@link #invalidate()}.
14863     * </p>
14864     *
14865     * <p>
14866     * This method should be invoked every time a subclass directly updates the
14867     * scroll parameters.
14868     * </p>
14869     *
14870     * @param startDelay the delay, in milliseconds, after which the animation
14871     *        should start; when the delay is 0, the animation starts
14872     *        immediately
14873     * @return true if the animation is played, false otherwise
14874     *
14875     * @see #scrollBy(int, int)
14876     * @see #scrollTo(int, int)
14877     * @see #isHorizontalScrollBarEnabled()
14878     * @see #isVerticalScrollBarEnabled()
14879     * @see #setHorizontalScrollBarEnabled(boolean)
14880     * @see #setVerticalScrollBarEnabled(boolean)
14881     */
14882    protected boolean awakenScrollBars(int startDelay) {
14883        return awakenScrollBars(startDelay, true);
14884    }
14885
14886    /**
14887     * <p>
14888     * Trigger the scrollbars to draw. When invoked this method starts an
14889     * animation to fade the scrollbars out after a fixed delay. If a subclass
14890     * provides animated scrolling, the start delay should equal the duration of
14891     * the scrolling animation.
14892     * </p>
14893     *
14894     * <p>
14895     * The animation starts only if at least one of the scrollbars is enabled,
14896     * as specified by {@link #isHorizontalScrollBarEnabled()} and
14897     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
14898     * this method returns true, and false otherwise. If the animation is
14899     * started, this method calls {@link #invalidate()} if the invalidate parameter
14900     * is set to true; in that case the caller
14901     * should not call {@link #invalidate()}.
14902     * </p>
14903     *
14904     * <p>
14905     * This method should be invoked every time a subclass directly updates the
14906     * scroll parameters.
14907     * </p>
14908     *
14909     * @param startDelay the delay, in milliseconds, after which the animation
14910     *        should start; when the delay is 0, the animation starts
14911     *        immediately
14912     *
14913     * @param invalidate Whether this method should call invalidate
14914     *
14915     * @return true if the animation is played, false otherwise
14916     *
14917     * @see #scrollBy(int, int)
14918     * @see #scrollTo(int, int)
14919     * @see #isHorizontalScrollBarEnabled()
14920     * @see #isVerticalScrollBarEnabled()
14921     * @see #setHorizontalScrollBarEnabled(boolean)
14922     * @see #setVerticalScrollBarEnabled(boolean)
14923     */
14924    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
14925        final ScrollabilityCache scrollCache = mScrollCache;
14926
14927        if (scrollCache == null || !scrollCache.fadeScrollBars) {
14928            return false;
14929        }
14930
14931        if (scrollCache.scrollBar == null) {
14932            scrollCache.scrollBar = new ScrollBarDrawable();
14933            scrollCache.scrollBar.setState(getDrawableState());
14934            scrollCache.scrollBar.setCallback(this);
14935        }
14936
14937        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
14938
14939            if (invalidate) {
14940                // Invalidate to show the scrollbars
14941                postInvalidateOnAnimation();
14942            }
14943
14944            if (scrollCache.state == ScrollabilityCache.OFF) {
14945                // FIXME: this is copied from WindowManagerService.
14946                // We should get this value from the system when it
14947                // is possible to do so.
14948                final int KEY_REPEAT_FIRST_DELAY = 750;
14949                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
14950            }
14951
14952            // Tell mScrollCache when we should start fading. This may
14953            // extend the fade start time if one was already scheduled
14954            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
14955            scrollCache.fadeStartTime = fadeStartTime;
14956            scrollCache.state = ScrollabilityCache.ON;
14957
14958            // Schedule our fader to run, unscheduling any old ones first
14959            if (mAttachInfo != null) {
14960                mAttachInfo.mHandler.removeCallbacks(scrollCache);
14961                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
14962            }
14963
14964            return true;
14965        }
14966
14967        return false;
14968    }
14969
14970    /**
14971     * Do not invalidate views which are not visible and which are not running an animation. They
14972     * will not get drawn and they should not set dirty flags as if they will be drawn
14973     */
14974    private boolean skipInvalidate() {
14975        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
14976                (!(mParent instanceof ViewGroup) ||
14977                        !((ViewGroup) mParent).isViewTransitioning(this));
14978    }
14979
14980    /**
14981     * Mark the area defined by dirty as needing to be drawn. If the view is
14982     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
14983     * point in the future.
14984     * <p>
14985     * This must be called from a UI thread. To call from a non-UI thread, call
14986     * {@link #postInvalidate()}.
14987     * <p>
14988     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
14989     * {@code dirty}.
14990     *
14991     * @param dirty the rectangle representing the bounds of the dirty region
14992     */
14993    public void invalidate(Rect dirty) {
14994        final int scrollX = mScrollX;
14995        final int scrollY = mScrollY;
14996        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
14997                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
14998    }
14999
15000    /**
15001     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
15002     * coordinates of the dirty rect are relative to the view. If the view is
15003     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15004     * point in the future.
15005     * <p>
15006     * This must be called from a UI thread. To call from a non-UI thread, call
15007     * {@link #postInvalidate()}.
15008     *
15009     * @param l the left position of the dirty region
15010     * @param t the top position of the dirty region
15011     * @param r the right position of the dirty region
15012     * @param b the bottom position of the dirty region
15013     */
15014    public void invalidate(int l, int t, int r, int b) {
15015        final int scrollX = mScrollX;
15016        final int scrollY = mScrollY;
15017        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
15018    }
15019
15020    /**
15021     * Invalidate the whole view. If the view is visible,
15022     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
15023     * the future.
15024     * <p>
15025     * This must be called from a UI thread. To call from a non-UI thread, call
15026     * {@link #postInvalidate()}.
15027     */
15028    public void invalidate() {
15029        invalidate(true);
15030    }
15031
15032    /**
15033     * This is where the invalidate() work actually happens. A full invalidate()
15034     * causes the drawing cache to be invalidated, but this function can be
15035     * called with invalidateCache set to false to skip that invalidation step
15036     * for cases that do not need it (for example, a component that remains at
15037     * the same dimensions with the same content).
15038     *
15039     * @param invalidateCache Whether the drawing cache for this view should be
15040     *            invalidated as well. This is usually true for a full
15041     *            invalidate, but may be set to false if the View's contents or
15042     *            dimensions have not changed.
15043     * @hide
15044     */
15045    public void invalidate(boolean invalidateCache) {
15046        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
15047    }
15048
15049    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
15050            boolean fullInvalidate) {
15051        if (mGhostView != null) {
15052            mGhostView.invalidate(true);
15053            return;
15054        }
15055
15056        if (skipInvalidate()) {
15057            return;
15058        }
15059
15060        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
15061                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
15062                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
15063                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
15064            if (fullInvalidate) {
15065                mLastIsOpaque = isOpaque();
15066                mPrivateFlags &= ~PFLAG_DRAWN;
15067            }
15068
15069            mPrivateFlags |= PFLAG_DIRTY;
15070
15071            if (invalidateCache) {
15072                mPrivateFlags |= PFLAG_INVALIDATED;
15073                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15074            }
15075
15076            // Propagate the damage rectangle to the parent view.
15077            final AttachInfo ai = mAttachInfo;
15078            final ViewParent p = mParent;
15079            if (p != null && ai != null && l < r && t < b) {
15080                final Rect damage = ai.mTmpInvalRect;
15081                damage.set(l, t, r, b);
15082                p.invalidateChild(this, damage);
15083            }
15084
15085            // Damage the entire projection receiver, if necessary.
15086            if (mBackground != null && mBackground.isProjected()) {
15087                final View receiver = getProjectionReceiver();
15088                if (receiver != null) {
15089                    receiver.damageInParent();
15090                }
15091            }
15092        }
15093    }
15094
15095    /**
15096     * @return this view's projection receiver, or {@code null} if none exists
15097     */
15098    private View getProjectionReceiver() {
15099        ViewParent p = getParent();
15100        while (p != null && p instanceof View) {
15101            final View v = (View) p;
15102            if (v.isProjectionReceiver()) {
15103                return v;
15104            }
15105            p = p.getParent();
15106        }
15107
15108        return null;
15109    }
15110
15111    /**
15112     * @return whether the view is a projection receiver
15113     */
15114    private boolean isProjectionReceiver() {
15115        return mBackground != null;
15116    }
15117
15118    /**
15119     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15120     * set any flags or handle all of the cases handled by the default invalidation methods.
15121     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15122     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15123     * walk up the hierarchy, transforming the dirty rect as necessary.
15124     *
15125     * The method also handles normal invalidation logic if display list properties are not
15126     * being used in this view. The invalidateParent and forceRedraw flags are used by that
15127     * backup approach, to handle these cases used in the various property-setting methods.
15128     *
15129     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15130     * are not being used in this view
15131     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15132     * list properties are not being used in this view
15133     */
15134    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15135        if (!isHardwareAccelerated()
15136                || !mRenderNode.isValid()
15137                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15138            if (invalidateParent) {
15139                invalidateParentCaches();
15140            }
15141            if (forceRedraw) {
15142                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15143            }
15144            invalidate(false);
15145        } else {
15146            damageInParent();
15147        }
15148    }
15149
15150    /**
15151     * Tells the parent view to damage this view's bounds.
15152     *
15153     * @hide
15154     */
15155    protected void damageInParent() {
15156        if (mParent != null && mAttachInfo != null) {
15157            mParent.onDescendantInvalidated(this, this);
15158        }
15159    }
15160
15161    /**
15162     * Utility method to transform a given Rect by the current matrix of this view.
15163     */
15164    void transformRect(final Rect rect) {
15165        if (!getMatrix().isIdentity()) {
15166            RectF boundingRect = mAttachInfo.mTmpTransformRect;
15167            boundingRect.set(rect);
15168            getMatrix().mapRect(boundingRect);
15169            rect.set((int) Math.floor(boundingRect.left),
15170                    (int) Math.floor(boundingRect.top),
15171                    (int) Math.ceil(boundingRect.right),
15172                    (int) Math.ceil(boundingRect.bottom));
15173        }
15174    }
15175
15176    /**
15177     * Used to indicate that the parent of this view should clear its caches. This functionality
15178     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15179     * which is necessary when various parent-managed properties of the view change, such as
15180     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15181     * clears the parent caches and does not causes an invalidate event.
15182     *
15183     * @hide
15184     */
15185    protected void invalidateParentCaches() {
15186        if (mParent instanceof View) {
15187            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15188        }
15189    }
15190
15191    /**
15192     * Used to indicate that the parent of this view should be invalidated. This functionality
15193     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15194     * which is necessary when various parent-managed properties of the view change, such as
15195     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15196     * an invalidation event to the parent.
15197     *
15198     * @hide
15199     */
15200    protected void invalidateParentIfNeeded() {
15201        if (isHardwareAccelerated() && mParent instanceof View) {
15202            ((View) mParent).invalidate(true);
15203        }
15204    }
15205
15206    /**
15207     * @hide
15208     */
15209    protected void invalidateParentIfNeededAndWasQuickRejected() {
15210        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15211            // View was rejected last time it was drawn by its parent; this may have changed
15212            invalidateParentIfNeeded();
15213        }
15214    }
15215
15216    /**
15217     * Indicates whether this View is opaque. An opaque View guarantees that it will
15218     * draw all the pixels overlapping its bounds using a fully opaque color.
15219     *
15220     * Subclasses of View should override this method whenever possible to indicate
15221     * whether an instance is opaque. Opaque Views are treated in a special way by
15222     * the View hierarchy, possibly allowing it to perform optimizations during
15223     * invalidate/draw passes.
15224     *
15225     * @return True if this View is guaranteed to be fully opaque, false otherwise.
15226     */
15227    @ViewDebug.ExportedProperty(category = "drawing")
15228    public boolean isOpaque() {
15229        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15230                getFinalAlpha() >= 1.0f;
15231    }
15232
15233    /**
15234     * @hide
15235     */
15236    protected void computeOpaqueFlags() {
15237        // Opaque if:
15238        //   - Has a background
15239        //   - Background is opaque
15240        //   - Doesn't have scrollbars or scrollbars overlay
15241
15242        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15243            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15244        } else {
15245            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15246        }
15247
15248        final int flags = mViewFlags;
15249        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15250                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15251                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15252            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15253        } else {
15254            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15255        }
15256    }
15257
15258    /**
15259     * @hide
15260     */
15261    protected boolean hasOpaqueScrollbars() {
15262        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15263    }
15264
15265    /**
15266     * @return A handler associated with the thread running the View. This
15267     * handler can be used to pump events in the UI events queue.
15268     */
15269    public Handler getHandler() {
15270        final AttachInfo attachInfo = mAttachInfo;
15271        if (attachInfo != null) {
15272            return attachInfo.mHandler;
15273        }
15274        return null;
15275    }
15276
15277    /**
15278     * Returns the queue of runnable for this view.
15279     *
15280     * @return the queue of runnables for this view
15281     */
15282    private HandlerActionQueue getRunQueue() {
15283        if (mRunQueue == null) {
15284            mRunQueue = new HandlerActionQueue();
15285        }
15286        return mRunQueue;
15287    }
15288
15289    /**
15290     * Gets the view root associated with the View.
15291     * @return The view root, or null if none.
15292     * @hide
15293     */
15294    public ViewRootImpl getViewRootImpl() {
15295        if (mAttachInfo != null) {
15296            return mAttachInfo.mViewRootImpl;
15297        }
15298        return null;
15299    }
15300
15301    /**
15302     * @hide
15303     */
15304    public ThreadedRenderer getThreadedRenderer() {
15305        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15306    }
15307
15308    /**
15309     * <p>Causes the Runnable to be added to the message queue.
15310     * The runnable will be run on the user interface thread.</p>
15311     *
15312     * @param action The Runnable that will be executed.
15313     *
15314     * @return Returns true if the Runnable was successfully placed in to the
15315     *         message queue.  Returns false on failure, usually because the
15316     *         looper processing the message queue is exiting.
15317     *
15318     * @see #postDelayed
15319     * @see #removeCallbacks
15320     */
15321    public boolean post(Runnable action) {
15322        final AttachInfo attachInfo = mAttachInfo;
15323        if (attachInfo != null) {
15324            return attachInfo.mHandler.post(action);
15325        }
15326
15327        // Postpone the runnable until we know on which thread it needs to run.
15328        // Assume that the runnable will be successfully placed after attach.
15329        getRunQueue().post(action);
15330        return true;
15331    }
15332
15333    /**
15334     * <p>Causes the Runnable to be added to the message queue, to be run
15335     * after the specified amount of time elapses.
15336     * The runnable will be run on the user interface thread.</p>
15337     *
15338     * @param action The Runnable that will be executed.
15339     * @param delayMillis The delay (in milliseconds) until the Runnable
15340     *        will be executed.
15341     *
15342     * @return true if the Runnable was successfully placed in to the
15343     *         message queue.  Returns false on failure, usually because the
15344     *         looper processing the message queue is exiting.  Note that a
15345     *         result of true does not mean the Runnable will be processed --
15346     *         if the looper is quit before the delivery time of the message
15347     *         occurs then the message will be dropped.
15348     *
15349     * @see #post
15350     * @see #removeCallbacks
15351     */
15352    public boolean postDelayed(Runnable action, long delayMillis) {
15353        final AttachInfo attachInfo = mAttachInfo;
15354        if (attachInfo != null) {
15355            return attachInfo.mHandler.postDelayed(action, delayMillis);
15356        }
15357
15358        // Postpone the runnable until we know on which thread it needs to run.
15359        // Assume that the runnable will be successfully placed after attach.
15360        getRunQueue().postDelayed(action, delayMillis);
15361        return true;
15362    }
15363
15364    /**
15365     * <p>Causes the Runnable to execute on the next animation time step.
15366     * The runnable will be run on the user interface thread.</p>
15367     *
15368     * @param action The Runnable that will be executed.
15369     *
15370     * @see #postOnAnimationDelayed
15371     * @see #removeCallbacks
15372     */
15373    public void postOnAnimation(Runnable action) {
15374        final AttachInfo attachInfo = mAttachInfo;
15375        if (attachInfo != null) {
15376            attachInfo.mViewRootImpl.mChoreographer.postCallback(
15377                    Choreographer.CALLBACK_ANIMATION, action, null);
15378        } else {
15379            // Postpone the runnable until we know
15380            // on which thread it needs to run.
15381            getRunQueue().post(action);
15382        }
15383    }
15384
15385    /**
15386     * <p>Causes the Runnable to execute on the next animation time step,
15387     * after the specified amount of time elapses.
15388     * The runnable will be run on the user interface thread.</p>
15389     *
15390     * @param action The Runnable that will be executed.
15391     * @param delayMillis The delay (in milliseconds) until the Runnable
15392     *        will be executed.
15393     *
15394     * @see #postOnAnimation
15395     * @see #removeCallbacks
15396     */
15397    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15398        final AttachInfo attachInfo = mAttachInfo;
15399        if (attachInfo != null) {
15400            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15401                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15402        } else {
15403            // Postpone the runnable until we know
15404            // on which thread it needs to run.
15405            getRunQueue().postDelayed(action, delayMillis);
15406        }
15407    }
15408
15409    /**
15410     * <p>Removes the specified Runnable from the message queue.</p>
15411     *
15412     * @param action The Runnable to remove from the message handling queue
15413     *
15414     * @return true if this view could ask the Handler to remove the Runnable,
15415     *         false otherwise. When the returned value is true, the Runnable
15416     *         may or may not have been actually removed from the message queue
15417     *         (for instance, if the Runnable was not in the queue already.)
15418     *
15419     * @see #post
15420     * @see #postDelayed
15421     * @see #postOnAnimation
15422     * @see #postOnAnimationDelayed
15423     */
15424    public boolean removeCallbacks(Runnable action) {
15425        if (action != null) {
15426            final AttachInfo attachInfo = mAttachInfo;
15427            if (attachInfo != null) {
15428                attachInfo.mHandler.removeCallbacks(action);
15429                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15430                        Choreographer.CALLBACK_ANIMATION, action, null);
15431            }
15432            getRunQueue().removeCallbacks(action);
15433        }
15434        return true;
15435    }
15436
15437    /**
15438     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15439     * Use this to invalidate the View from a non-UI thread.</p>
15440     *
15441     * <p>This method can be invoked from outside of the UI thread
15442     * only when this View is attached to a window.</p>
15443     *
15444     * @see #invalidate()
15445     * @see #postInvalidateDelayed(long)
15446     */
15447    public void postInvalidate() {
15448        postInvalidateDelayed(0);
15449    }
15450
15451    /**
15452     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15453     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15454     *
15455     * <p>This method can be invoked from outside of the UI thread
15456     * only when this View is attached to a window.</p>
15457     *
15458     * @param left The left coordinate of the rectangle to invalidate.
15459     * @param top The top coordinate of the rectangle to invalidate.
15460     * @param right The right coordinate of the rectangle to invalidate.
15461     * @param bottom The bottom coordinate of the rectangle to invalidate.
15462     *
15463     * @see #invalidate(int, int, int, int)
15464     * @see #invalidate(Rect)
15465     * @see #postInvalidateDelayed(long, int, int, int, int)
15466     */
15467    public void postInvalidate(int left, int top, int right, int bottom) {
15468        postInvalidateDelayed(0, left, top, right, bottom);
15469    }
15470
15471    /**
15472     * <p>Cause an invalidate to happen on a subsequent cycle through the event
15473     * loop. Waits for the specified amount of time.</p>
15474     *
15475     * <p>This method can be invoked from outside of the UI thread
15476     * only when this View is attached to a window.</p>
15477     *
15478     * @param delayMilliseconds the duration in milliseconds to delay the
15479     *         invalidation by
15480     *
15481     * @see #invalidate()
15482     * @see #postInvalidate()
15483     */
15484    public void postInvalidateDelayed(long delayMilliseconds) {
15485        // We try only with the AttachInfo because there's no point in invalidating
15486        // if we are not attached to our window
15487        final AttachInfo attachInfo = mAttachInfo;
15488        if (attachInfo != null) {
15489            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15490        }
15491    }
15492
15493    /**
15494     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15495     * through the event loop. Waits for the specified amount of time.</p>
15496     *
15497     * <p>This method can be invoked from outside of the UI thread
15498     * only when this View is attached to a window.</p>
15499     *
15500     * @param delayMilliseconds the duration in milliseconds to delay the
15501     *         invalidation by
15502     * @param left The left coordinate of the rectangle to invalidate.
15503     * @param top The top coordinate of the rectangle to invalidate.
15504     * @param right The right coordinate of the rectangle to invalidate.
15505     * @param bottom The bottom coordinate of the rectangle to invalidate.
15506     *
15507     * @see #invalidate(int, int, int, int)
15508     * @see #invalidate(Rect)
15509     * @see #postInvalidate(int, int, int, int)
15510     */
15511    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15512            int right, int bottom) {
15513
15514        // We try only with the AttachInfo because there's no point in invalidating
15515        // if we are not attached to our window
15516        final AttachInfo attachInfo = mAttachInfo;
15517        if (attachInfo != null) {
15518            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15519            info.target = this;
15520            info.left = left;
15521            info.top = top;
15522            info.right = right;
15523            info.bottom = bottom;
15524
15525            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15526        }
15527    }
15528
15529    /**
15530     * <p>Cause an invalidate to happen on the next animation time step, typically the
15531     * next display frame.</p>
15532     *
15533     * <p>This method can be invoked from outside of the UI thread
15534     * only when this View is attached to a window.</p>
15535     *
15536     * @see #invalidate()
15537     */
15538    public void postInvalidateOnAnimation() {
15539        // We try only with the AttachInfo because there's no point in invalidating
15540        // if we are not attached to our window
15541        final AttachInfo attachInfo = mAttachInfo;
15542        if (attachInfo != null) {
15543            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
15544        }
15545    }
15546
15547    /**
15548     * <p>Cause an invalidate of the specified area to happen on the next animation
15549     * time step, typically the next display frame.</p>
15550     *
15551     * <p>This method can be invoked from outside of the UI thread
15552     * only when this View is attached to a window.</p>
15553     *
15554     * @param left The left coordinate of the rectangle to invalidate.
15555     * @param top The top coordinate of the rectangle to invalidate.
15556     * @param right The right coordinate of the rectangle to invalidate.
15557     * @param bottom The bottom coordinate of the rectangle to invalidate.
15558     *
15559     * @see #invalidate(int, int, int, int)
15560     * @see #invalidate(Rect)
15561     */
15562    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
15563        // We try only with the AttachInfo because there's no point in invalidating
15564        // if we are not attached to our window
15565        final AttachInfo attachInfo = mAttachInfo;
15566        if (attachInfo != null) {
15567            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15568            info.target = this;
15569            info.left = left;
15570            info.top = top;
15571            info.right = right;
15572            info.bottom = bottom;
15573
15574            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
15575        }
15576    }
15577
15578    /**
15579     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
15580     * This event is sent at most once every
15581     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
15582     */
15583    private void postSendViewScrolledAccessibilityEventCallback() {
15584        if (mSendViewScrolledAccessibilityEvent == null) {
15585            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
15586        }
15587        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
15588            mSendViewScrolledAccessibilityEvent.mIsPending = true;
15589            postDelayed(mSendViewScrolledAccessibilityEvent,
15590                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
15591        }
15592    }
15593
15594    /**
15595     * Called by a parent to request that a child update its values for mScrollX
15596     * and mScrollY if necessary. This will typically be done if the child is
15597     * animating a scroll using a {@link android.widget.Scroller Scroller}
15598     * object.
15599     */
15600    public void computeScroll() {
15601    }
15602
15603    /**
15604     * <p>Indicate whether the horizontal edges are faded when the view is
15605     * scrolled horizontally.</p>
15606     *
15607     * @return true if the horizontal edges should are faded on scroll, false
15608     *         otherwise
15609     *
15610     * @see #setHorizontalFadingEdgeEnabled(boolean)
15611     *
15612     * @attr ref android.R.styleable#View_requiresFadingEdge
15613     */
15614    public boolean isHorizontalFadingEdgeEnabled() {
15615        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
15616    }
15617
15618    /**
15619     * <p>Define whether the horizontal edges should be faded when this view
15620     * is scrolled horizontally.</p>
15621     *
15622     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
15623     *                                    be faded when the view is scrolled
15624     *                                    horizontally
15625     *
15626     * @see #isHorizontalFadingEdgeEnabled()
15627     *
15628     * @attr ref android.R.styleable#View_requiresFadingEdge
15629     */
15630    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
15631        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
15632            if (horizontalFadingEdgeEnabled) {
15633                initScrollCache();
15634            }
15635
15636            mViewFlags ^= FADING_EDGE_HORIZONTAL;
15637        }
15638    }
15639
15640    /**
15641     * <p>Indicate whether the vertical edges are faded when the view is
15642     * scrolled horizontally.</p>
15643     *
15644     * @return true if the vertical edges should are faded on scroll, false
15645     *         otherwise
15646     *
15647     * @see #setVerticalFadingEdgeEnabled(boolean)
15648     *
15649     * @attr ref android.R.styleable#View_requiresFadingEdge
15650     */
15651    public boolean isVerticalFadingEdgeEnabled() {
15652        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
15653    }
15654
15655    /**
15656     * <p>Define whether the vertical edges should be faded when this view
15657     * is scrolled vertically.</p>
15658     *
15659     * @param verticalFadingEdgeEnabled true if the vertical edges should
15660     *                                  be faded when the view is scrolled
15661     *                                  vertically
15662     *
15663     * @see #isVerticalFadingEdgeEnabled()
15664     *
15665     * @attr ref android.R.styleable#View_requiresFadingEdge
15666     */
15667    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
15668        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
15669            if (verticalFadingEdgeEnabled) {
15670                initScrollCache();
15671            }
15672
15673            mViewFlags ^= FADING_EDGE_VERTICAL;
15674        }
15675    }
15676
15677    /**
15678     * Returns the strength, or intensity, of the top faded edge. The strength is
15679     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15680     * returns 0.0 or 1.0 but no value in between.
15681     *
15682     * Subclasses should override this method to provide a smoother fade transition
15683     * when scrolling occurs.
15684     *
15685     * @return the intensity of the top fade as a float between 0.0f and 1.0f
15686     */
15687    protected float getTopFadingEdgeStrength() {
15688        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
15689    }
15690
15691    /**
15692     * Returns the strength, or intensity, of the bottom faded edge. The strength is
15693     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15694     * returns 0.0 or 1.0 but no value in between.
15695     *
15696     * Subclasses should override this method to provide a smoother fade transition
15697     * when scrolling occurs.
15698     *
15699     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
15700     */
15701    protected float getBottomFadingEdgeStrength() {
15702        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
15703                computeVerticalScrollRange() ? 1.0f : 0.0f;
15704    }
15705
15706    /**
15707     * Returns the strength, or intensity, of the left faded edge. The strength is
15708     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15709     * returns 0.0 or 1.0 but no value in between.
15710     *
15711     * Subclasses should override this method to provide a smoother fade transition
15712     * when scrolling occurs.
15713     *
15714     * @return the intensity of the left fade as a float between 0.0f and 1.0f
15715     */
15716    protected float getLeftFadingEdgeStrength() {
15717        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
15718    }
15719
15720    /**
15721     * Returns the strength, or intensity, of the right faded edge. The strength is
15722     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
15723     * returns 0.0 or 1.0 but no value in between.
15724     *
15725     * Subclasses should override this method to provide a smoother fade transition
15726     * when scrolling occurs.
15727     *
15728     * @return the intensity of the right fade as a float between 0.0f and 1.0f
15729     */
15730    protected float getRightFadingEdgeStrength() {
15731        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
15732                computeHorizontalScrollRange() ? 1.0f : 0.0f;
15733    }
15734
15735    /**
15736     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
15737     * scrollbar is not drawn by default.</p>
15738     *
15739     * @return true if the horizontal scrollbar should be painted, false
15740     *         otherwise
15741     *
15742     * @see #setHorizontalScrollBarEnabled(boolean)
15743     */
15744    public boolean isHorizontalScrollBarEnabled() {
15745        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
15746    }
15747
15748    /**
15749     * <p>Define whether the horizontal scrollbar should be drawn or not. The
15750     * scrollbar is not drawn by default.</p>
15751     *
15752     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
15753     *                                   be painted
15754     *
15755     * @see #isHorizontalScrollBarEnabled()
15756     */
15757    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
15758        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
15759            mViewFlags ^= SCROLLBARS_HORIZONTAL;
15760            computeOpaqueFlags();
15761            resolvePadding();
15762        }
15763    }
15764
15765    /**
15766     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
15767     * scrollbar is not drawn by default.</p>
15768     *
15769     * @return true if the vertical scrollbar should be painted, false
15770     *         otherwise
15771     *
15772     * @see #setVerticalScrollBarEnabled(boolean)
15773     */
15774    public boolean isVerticalScrollBarEnabled() {
15775        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
15776    }
15777
15778    /**
15779     * <p>Define whether the vertical scrollbar should be drawn or not. The
15780     * scrollbar is not drawn by default.</p>
15781     *
15782     * @param verticalScrollBarEnabled true if the vertical scrollbar should
15783     *                                 be painted
15784     *
15785     * @see #isVerticalScrollBarEnabled()
15786     */
15787    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
15788        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
15789            mViewFlags ^= SCROLLBARS_VERTICAL;
15790            computeOpaqueFlags();
15791            resolvePadding();
15792        }
15793    }
15794
15795    /**
15796     * @hide
15797     */
15798    protected void recomputePadding() {
15799        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
15800    }
15801
15802    /**
15803     * Define whether scrollbars will fade when the view is not scrolling.
15804     *
15805     * @param fadeScrollbars whether to enable fading
15806     *
15807     * @attr ref android.R.styleable#View_fadeScrollbars
15808     */
15809    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
15810        initScrollCache();
15811        final ScrollabilityCache scrollabilityCache = mScrollCache;
15812        scrollabilityCache.fadeScrollBars = fadeScrollbars;
15813        if (fadeScrollbars) {
15814            scrollabilityCache.state = ScrollabilityCache.OFF;
15815        } else {
15816            scrollabilityCache.state = ScrollabilityCache.ON;
15817        }
15818    }
15819
15820    /**
15821     *
15822     * Returns true if scrollbars will fade when this view is not scrolling
15823     *
15824     * @return true if scrollbar fading is enabled
15825     *
15826     * @attr ref android.R.styleable#View_fadeScrollbars
15827     */
15828    public boolean isScrollbarFadingEnabled() {
15829        return mScrollCache != null && mScrollCache.fadeScrollBars;
15830    }
15831
15832    /**
15833     *
15834     * Returns the delay before scrollbars fade.
15835     *
15836     * @return the delay before scrollbars fade
15837     *
15838     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15839     */
15840    public int getScrollBarDefaultDelayBeforeFade() {
15841        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
15842                mScrollCache.scrollBarDefaultDelayBeforeFade;
15843    }
15844
15845    /**
15846     * Define the delay before scrollbars fade.
15847     *
15848     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
15849     *
15850     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
15851     */
15852    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
15853        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
15854    }
15855
15856    /**
15857     *
15858     * Returns the scrollbar fade duration.
15859     *
15860     * @return the scrollbar fade duration, in milliseconds
15861     *
15862     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15863     */
15864    public int getScrollBarFadeDuration() {
15865        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
15866                mScrollCache.scrollBarFadeDuration;
15867    }
15868
15869    /**
15870     * Define the scrollbar fade duration.
15871     *
15872     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
15873     *
15874     * @attr ref android.R.styleable#View_scrollbarFadeDuration
15875     */
15876    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
15877        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
15878    }
15879
15880    /**
15881     *
15882     * Returns the scrollbar size.
15883     *
15884     * @return the scrollbar size
15885     *
15886     * @attr ref android.R.styleable#View_scrollbarSize
15887     */
15888    public int getScrollBarSize() {
15889        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
15890                mScrollCache.scrollBarSize;
15891    }
15892
15893    /**
15894     * Define the scrollbar size.
15895     *
15896     * @param scrollBarSize - the scrollbar size
15897     *
15898     * @attr ref android.R.styleable#View_scrollbarSize
15899     */
15900    public void setScrollBarSize(int scrollBarSize) {
15901        getScrollCache().scrollBarSize = scrollBarSize;
15902    }
15903
15904    /**
15905     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
15906     * inset. When inset, they add to the padding of the view. And the scrollbars
15907     * can be drawn inside the padding area or on the edge of the view. For example,
15908     * if a view has a background drawable and you want to draw the scrollbars
15909     * inside the padding specified by the drawable, you can use
15910     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
15911     * appear at the edge of the view, ignoring the padding, then you can use
15912     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
15913     * @param style the style of the scrollbars. Should be one of
15914     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
15915     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
15916     * @see #SCROLLBARS_INSIDE_OVERLAY
15917     * @see #SCROLLBARS_INSIDE_INSET
15918     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15919     * @see #SCROLLBARS_OUTSIDE_INSET
15920     *
15921     * @attr ref android.R.styleable#View_scrollbarStyle
15922     */
15923    public void setScrollBarStyle(@ScrollBarStyle int style) {
15924        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
15925            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
15926            computeOpaqueFlags();
15927            resolvePadding();
15928        }
15929    }
15930
15931    /**
15932     * <p>Returns the current scrollbar style.</p>
15933     * @return the current scrollbar style
15934     * @see #SCROLLBARS_INSIDE_OVERLAY
15935     * @see #SCROLLBARS_INSIDE_INSET
15936     * @see #SCROLLBARS_OUTSIDE_OVERLAY
15937     * @see #SCROLLBARS_OUTSIDE_INSET
15938     *
15939     * @attr ref android.R.styleable#View_scrollbarStyle
15940     */
15941    @ViewDebug.ExportedProperty(mapping = {
15942            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
15943            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
15944            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
15945            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
15946    })
15947    @ScrollBarStyle
15948    public int getScrollBarStyle() {
15949        return mViewFlags & SCROLLBARS_STYLE_MASK;
15950    }
15951
15952    /**
15953     * <p>Compute the horizontal range that the horizontal scrollbar
15954     * represents.</p>
15955     *
15956     * <p>The range is expressed in arbitrary units that must be the same as the
15957     * units used by {@link #computeHorizontalScrollExtent()} and
15958     * {@link #computeHorizontalScrollOffset()}.</p>
15959     *
15960     * <p>The default range is the drawing width of this view.</p>
15961     *
15962     * @return the total horizontal range represented by the horizontal
15963     *         scrollbar
15964     *
15965     * @see #computeHorizontalScrollExtent()
15966     * @see #computeHorizontalScrollOffset()
15967     * @see android.widget.ScrollBarDrawable
15968     */
15969    protected int computeHorizontalScrollRange() {
15970        return getWidth();
15971    }
15972
15973    /**
15974     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
15975     * within the horizontal range. This value is used to compute the position
15976     * of the thumb within the scrollbar's track.</p>
15977     *
15978     * <p>The range is expressed in arbitrary units that must be the same as the
15979     * units used by {@link #computeHorizontalScrollRange()} and
15980     * {@link #computeHorizontalScrollExtent()}.</p>
15981     *
15982     * <p>The default offset is the scroll offset of this view.</p>
15983     *
15984     * @return the horizontal offset of the scrollbar's thumb
15985     *
15986     * @see #computeHorizontalScrollRange()
15987     * @see #computeHorizontalScrollExtent()
15988     * @see android.widget.ScrollBarDrawable
15989     */
15990    protected int computeHorizontalScrollOffset() {
15991        return mScrollX;
15992    }
15993
15994    /**
15995     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
15996     * within the horizontal range. This value is used to compute the length
15997     * of the thumb within the scrollbar's track.</p>
15998     *
15999     * <p>The range is expressed in arbitrary units that must be the same as the
16000     * units used by {@link #computeHorizontalScrollRange()} and
16001     * {@link #computeHorizontalScrollOffset()}.</p>
16002     *
16003     * <p>The default extent is the drawing width of this view.</p>
16004     *
16005     * @return the horizontal extent of the scrollbar's thumb
16006     *
16007     * @see #computeHorizontalScrollRange()
16008     * @see #computeHorizontalScrollOffset()
16009     * @see android.widget.ScrollBarDrawable
16010     */
16011    protected int computeHorizontalScrollExtent() {
16012        return getWidth();
16013    }
16014
16015    /**
16016     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
16017     *
16018     * <p>The range is expressed in arbitrary units that must be the same as the
16019     * units used by {@link #computeVerticalScrollExtent()} and
16020     * {@link #computeVerticalScrollOffset()}.</p>
16021     *
16022     * @return the total vertical range represented by the vertical scrollbar
16023     *
16024     * <p>The default range is the drawing height of this view.</p>
16025     *
16026     * @see #computeVerticalScrollExtent()
16027     * @see #computeVerticalScrollOffset()
16028     * @see android.widget.ScrollBarDrawable
16029     */
16030    protected int computeVerticalScrollRange() {
16031        return getHeight();
16032    }
16033
16034    /**
16035     * <p>Compute the vertical offset of the vertical scrollbar's thumb
16036     * within the horizontal range. This value is used to compute the position
16037     * of the thumb within the scrollbar's track.</p>
16038     *
16039     * <p>The range is expressed in arbitrary units that must be the same as the
16040     * units used by {@link #computeVerticalScrollRange()} and
16041     * {@link #computeVerticalScrollExtent()}.</p>
16042     *
16043     * <p>The default offset is the scroll offset of this view.</p>
16044     *
16045     * @return the vertical offset of the scrollbar's thumb
16046     *
16047     * @see #computeVerticalScrollRange()
16048     * @see #computeVerticalScrollExtent()
16049     * @see android.widget.ScrollBarDrawable
16050     */
16051    protected int computeVerticalScrollOffset() {
16052        return mScrollY;
16053    }
16054
16055    /**
16056     * <p>Compute the vertical extent of the vertical scrollbar's thumb
16057     * within the vertical range. This value is used to compute the length
16058     * of the thumb within the scrollbar's track.</p>
16059     *
16060     * <p>The range is expressed in arbitrary units that must be the same as the
16061     * units used by {@link #computeVerticalScrollRange()} and
16062     * {@link #computeVerticalScrollOffset()}.</p>
16063     *
16064     * <p>The default extent is the drawing height of this view.</p>
16065     *
16066     * @return the vertical extent of the scrollbar's thumb
16067     *
16068     * @see #computeVerticalScrollRange()
16069     * @see #computeVerticalScrollOffset()
16070     * @see android.widget.ScrollBarDrawable
16071     */
16072    protected int computeVerticalScrollExtent() {
16073        return getHeight();
16074    }
16075
16076    /**
16077     * Check if this view can be scrolled horizontally in a certain direction.
16078     *
16079     * @param direction Negative to check scrolling left, positive to check scrolling right.
16080     * @return true if this view can be scrolled in the specified direction, false otherwise.
16081     */
16082    public boolean canScrollHorizontally(int direction) {
16083        final int offset = computeHorizontalScrollOffset();
16084        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
16085        if (range == 0) return false;
16086        if (direction < 0) {
16087            return offset > 0;
16088        } else {
16089            return offset < range - 1;
16090        }
16091    }
16092
16093    /**
16094     * Check if this view can be scrolled vertically in a certain direction.
16095     *
16096     * @param direction Negative to check scrolling up, positive to check scrolling down.
16097     * @return true if this view can be scrolled in the specified direction, false otherwise.
16098     */
16099    public boolean canScrollVertically(int direction) {
16100        final int offset = computeVerticalScrollOffset();
16101        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16102        if (range == 0) return false;
16103        if (direction < 0) {
16104            return offset > 0;
16105        } else {
16106            return offset < range - 1;
16107        }
16108    }
16109
16110    void getScrollIndicatorBounds(@NonNull Rect out) {
16111        out.left = mScrollX;
16112        out.right = mScrollX + mRight - mLeft;
16113        out.top = mScrollY;
16114        out.bottom = mScrollY + mBottom - mTop;
16115    }
16116
16117    private void onDrawScrollIndicators(Canvas c) {
16118        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16119            // No scroll indicators enabled.
16120            return;
16121        }
16122
16123        final Drawable dr = mScrollIndicatorDrawable;
16124        if (dr == null) {
16125            // Scroll indicators aren't supported here.
16126            return;
16127        }
16128
16129        final int h = dr.getIntrinsicHeight();
16130        final int w = dr.getIntrinsicWidth();
16131        final Rect rect = mAttachInfo.mTmpInvalRect;
16132        getScrollIndicatorBounds(rect);
16133
16134        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16135            final boolean canScrollUp = canScrollVertically(-1);
16136            if (canScrollUp) {
16137                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16138                dr.draw(c);
16139            }
16140        }
16141
16142        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16143            final boolean canScrollDown = canScrollVertically(1);
16144            if (canScrollDown) {
16145                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16146                dr.draw(c);
16147            }
16148        }
16149
16150        final int leftRtl;
16151        final int rightRtl;
16152        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16153            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16154            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16155        } else {
16156            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16157            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16158        }
16159
16160        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16161        if ((mPrivateFlags3 & leftMask) != 0) {
16162            final boolean canScrollLeft = canScrollHorizontally(-1);
16163            if (canScrollLeft) {
16164                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16165                dr.draw(c);
16166            }
16167        }
16168
16169        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16170        if ((mPrivateFlags3 & rightMask) != 0) {
16171            final boolean canScrollRight = canScrollHorizontally(1);
16172            if (canScrollRight) {
16173                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16174                dr.draw(c);
16175            }
16176        }
16177    }
16178
16179    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16180            @Nullable Rect touchBounds) {
16181        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16182        if (bounds == null) {
16183            return;
16184        }
16185        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16186        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16187                && !isVerticalScrollBarHidden();
16188        final int size = getHorizontalScrollbarHeight();
16189        final int verticalScrollBarGap = drawVerticalScrollBar ?
16190                getVerticalScrollbarWidth() : 0;
16191        final int width = mRight - mLeft;
16192        final int height = mBottom - mTop;
16193        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16194        bounds.left = mScrollX + (mPaddingLeft & inside);
16195        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16196        bounds.bottom = bounds.top + size;
16197
16198        if (touchBounds == null) {
16199            return;
16200        }
16201        if (touchBounds != bounds) {
16202            touchBounds.set(bounds);
16203        }
16204        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16205        if (touchBounds.height() < minTouchTarget) {
16206            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16207            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16208            touchBounds.top = touchBounds.bottom - minTouchTarget;
16209        }
16210        if (touchBounds.width() < minTouchTarget) {
16211            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16212            touchBounds.left -= adjust;
16213            touchBounds.right = touchBounds.left + minTouchTarget;
16214        }
16215    }
16216
16217    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16218        if (mRoundScrollbarRenderer == null) {
16219            getStraightVerticalScrollBarBounds(bounds, touchBounds);
16220        } else {
16221            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16222        }
16223    }
16224
16225    private void getRoundVerticalScrollBarBounds(Rect bounds) {
16226        final int width = mRight - mLeft;
16227        final int height = mBottom - mTop;
16228        // Do not take padding into account as we always want the scrollbars
16229        // to hug the screen for round wearable devices.
16230        bounds.left = mScrollX;
16231        bounds.top = mScrollY;
16232        bounds.right = bounds.left + width;
16233        bounds.bottom = mScrollY + height;
16234    }
16235
16236    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16237            @Nullable Rect touchBounds) {
16238        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16239        if (bounds == null) {
16240            return;
16241        }
16242        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16243        final int size = getVerticalScrollbarWidth();
16244        int verticalScrollbarPosition = mVerticalScrollbarPosition;
16245        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16246            verticalScrollbarPosition = isLayoutRtl() ?
16247                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16248        }
16249        final int width = mRight - mLeft;
16250        final int height = mBottom - mTop;
16251        switch (verticalScrollbarPosition) {
16252            default:
16253            case SCROLLBAR_POSITION_RIGHT:
16254                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16255                break;
16256            case SCROLLBAR_POSITION_LEFT:
16257                bounds.left = mScrollX + (mUserPaddingLeft & inside);
16258                break;
16259        }
16260        bounds.top = mScrollY + (mPaddingTop & inside);
16261        bounds.right = bounds.left + size;
16262        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16263
16264        if (touchBounds == null) {
16265            return;
16266        }
16267        if (touchBounds != bounds) {
16268            touchBounds.set(bounds);
16269        }
16270        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16271        if (touchBounds.width() < minTouchTarget) {
16272            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16273            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16274                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16275                touchBounds.left = touchBounds.right - minTouchTarget;
16276            } else {
16277                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16278                touchBounds.right = touchBounds.left + minTouchTarget;
16279            }
16280        }
16281        if (touchBounds.height() < minTouchTarget) {
16282            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16283            touchBounds.top -= adjust;
16284            touchBounds.bottom = touchBounds.top + minTouchTarget;
16285        }
16286    }
16287
16288    /**
16289     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16290     * scrollbars are painted only if they have been awakened first.</p>
16291     *
16292     * @param canvas the canvas on which to draw the scrollbars
16293     *
16294     * @see #awakenScrollBars(int)
16295     */
16296    protected final void onDrawScrollBars(Canvas canvas) {
16297        // scrollbars are drawn only when the animation is running
16298        final ScrollabilityCache cache = mScrollCache;
16299
16300        if (cache != null) {
16301
16302            int state = cache.state;
16303
16304            if (state == ScrollabilityCache.OFF) {
16305                return;
16306            }
16307
16308            boolean invalidate = false;
16309
16310            if (state == ScrollabilityCache.FADING) {
16311                // We're fading -- get our fade interpolation
16312                if (cache.interpolatorValues == null) {
16313                    cache.interpolatorValues = new float[1];
16314                }
16315
16316                float[] values = cache.interpolatorValues;
16317
16318                // Stops the animation if we're done
16319                if (cache.scrollBarInterpolator.timeToValues(values) ==
16320                        Interpolator.Result.FREEZE_END) {
16321                    cache.state = ScrollabilityCache.OFF;
16322                } else {
16323                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16324                }
16325
16326                // This will make the scroll bars inval themselves after
16327                // drawing. We only want this when we're fading so that
16328                // we prevent excessive redraws
16329                invalidate = true;
16330            } else {
16331                // We're just on -- but we may have been fading before so
16332                // reset alpha
16333                cache.scrollBar.mutate().setAlpha(255);
16334            }
16335
16336            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16337            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16338                    && !isVerticalScrollBarHidden();
16339
16340            // Fork out the scroll bar drawing for round wearable devices.
16341            if (mRoundScrollbarRenderer != null) {
16342                if (drawVerticalScrollBar) {
16343                    final Rect bounds = cache.mScrollBarBounds;
16344                    getVerticalScrollBarBounds(bounds, null);
16345                    mRoundScrollbarRenderer.drawRoundScrollbars(
16346                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16347                    if (invalidate) {
16348                        invalidate();
16349                    }
16350                }
16351                // Do not draw horizontal scroll bars for round wearable devices.
16352            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16353                final ScrollBarDrawable scrollBar = cache.scrollBar;
16354
16355                if (drawHorizontalScrollBar) {
16356                    scrollBar.setParameters(computeHorizontalScrollRange(),
16357                            computeHorizontalScrollOffset(),
16358                            computeHorizontalScrollExtent(), false);
16359                    final Rect bounds = cache.mScrollBarBounds;
16360                    getHorizontalScrollBarBounds(bounds, null);
16361                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16362                            bounds.right, bounds.bottom);
16363                    if (invalidate) {
16364                        invalidate(bounds);
16365                    }
16366                }
16367
16368                if (drawVerticalScrollBar) {
16369                    scrollBar.setParameters(computeVerticalScrollRange(),
16370                            computeVerticalScrollOffset(),
16371                            computeVerticalScrollExtent(), true);
16372                    final Rect bounds = cache.mScrollBarBounds;
16373                    getVerticalScrollBarBounds(bounds, null);
16374                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16375                            bounds.right, bounds.bottom);
16376                    if (invalidate) {
16377                        invalidate(bounds);
16378                    }
16379                }
16380            }
16381        }
16382    }
16383
16384    /**
16385     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16386     * FastScroller is visible.
16387     * @return whether to temporarily hide the vertical scrollbar
16388     * @hide
16389     */
16390    protected boolean isVerticalScrollBarHidden() {
16391        return false;
16392    }
16393
16394    /**
16395     * <p>Draw the horizontal scrollbar if
16396     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16397     *
16398     * @param canvas the canvas on which to draw the scrollbar
16399     * @param scrollBar the scrollbar's drawable
16400     *
16401     * @see #isHorizontalScrollBarEnabled()
16402     * @see #computeHorizontalScrollRange()
16403     * @see #computeHorizontalScrollExtent()
16404     * @see #computeHorizontalScrollOffset()
16405     * @see android.widget.ScrollBarDrawable
16406     * @hide
16407     */
16408    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16409            int l, int t, int r, int b) {
16410        scrollBar.setBounds(l, t, r, b);
16411        scrollBar.draw(canvas);
16412    }
16413
16414    /**
16415     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16416     * returns true.</p>
16417     *
16418     * @param canvas the canvas on which to draw the scrollbar
16419     * @param scrollBar the scrollbar's drawable
16420     *
16421     * @see #isVerticalScrollBarEnabled()
16422     * @see #computeVerticalScrollRange()
16423     * @see #computeVerticalScrollExtent()
16424     * @see #computeVerticalScrollOffset()
16425     * @see android.widget.ScrollBarDrawable
16426     * @hide
16427     */
16428    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16429            int l, int t, int r, int b) {
16430        scrollBar.setBounds(l, t, r, b);
16431        scrollBar.draw(canvas);
16432    }
16433
16434    /**
16435     * Implement this to do your drawing.
16436     *
16437     * @param canvas the canvas on which the background will be drawn
16438     */
16439    protected void onDraw(Canvas canvas) {
16440    }
16441
16442    /*
16443     * Caller is responsible for calling requestLayout if necessary.
16444     * (This allows addViewInLayout to not request a new layout.)
16445     */
16446    void assignParent(ViewParent parent) {
16447        if (mParent == null) {
16448            mParent = parent;
16449        } else if (parent == null) {
16450            mParent = null;
16451        } else {
16452            throw new RuntimeException("view " + this + " being added, but"
16453                    + " it already has a parent");
16454        }
16455    }
16456
16457    /**
16458     * This is called when the view is attached to a window.  At this point it
16459     * has a Surface and will start drawing.  Note that this function is
16460     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16461     * however it may be called any time before the first onDraw -- including
16462     * before or after {@link #onMeasure(int, int)}.
16463     *
16464     * @see #onDetachedFromWindow()
16465     */
16466    @CallSuper
16467    protected void onAttachedToWindow() {
16468        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16469            mParent.requestTransparentRegion(this);
16470        }
16471
16472        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16473
16474        jumpDrawablesToCurrentState();
16475
16476        resetSubtreeAccessibilityStateChanged();
16477
16478        // rebuild, since Outline not maintained while View is detached
16479        rebuildOutline();
16480
16481        if (isFocused()) {
16482            InputMethodManager imm = InputMethodManager.peekInstance();
16483            if (imm != null) {
16484                imm.focusIn(this);
16485            }
16486        }
16487    }
16488
16489    /**
16490     * Resolve all RTL related properties.
16491     *
16492     * @return true if resolution of RTL properties has been done
16493     *
16494     * @hide
16495     */
16496    public boolean resolveRtlPropertiesIfNeeded() {
16497        if (!needRtlPropertiesResolution()) return false;
16498
16499        // Order is important here: LayoutDirection MUST be resolved first
16500        if (!isLayoutDirectionResolved()) {
16501            resolveLayoutDirection();
16502            resolveLayoutParams();
16503        }
16504        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16505        if (!isTextDirectionResolved()) {
16506            resolveTextDirection();
16507        }
16508        if (!isTextAlignmentResolved()) {
16509            resolveTextAlignment();
16510        }
16511        // Should resolve Drawables before Padding because we need the layout direction of the
16512        // Drawable to correctly resolve Padding.
16513        if (!areDrawablesResolved()) {
16514            resolveDrawables();
16515        }
16516        if (!isPaddingResolved()) {
16517            resolvePadding();
16518        }
16519        onRtlPropertiesChanged(getLayoutDirection());
16520        return true;
16521    }
16522
16523    /**
16524     * Reset resolution of all RTL related properties.
16525     *
16526     * @hide
16527     */
16528    public void resetRtlProperties() {
16529        resetResolvedLayoutDirection();
16530        resetResolvedTextDirection();
16531        resetResolvedTextAlignment();
16532        resetResolvedPadding();
16533        resetResolvedDrawables();
16534    }
16535
16536    /**
16537     * @see #onScreenStateChanged(int)
16538     */
16539    void dispatchScreenStateChanged(int screenState) {
16540        onScreenStateChanged(screenState);
16541    }
16542
16543    /**
16544     * This method is called whenever the state of the screen this view is
16545     * attached to changes. A state change will usually occurs when the screen
16546     * turns on or off (whether it happens automatically or the user does it
16547     * manually.)
16548     *
16549     * @param screenState The new state of the screen. Can be either
16550     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
16551     */
16552    public void onScreenStateChanged(int screenState) {
16553    }
16554
16555    /**
16556     * @see #onMovedToDisplay(int, Configuration)
16557     */
16558    void dispatchMovedToDisplay(Display display, Configuration config) {
16559        mAttachInfo.mDisplay = display;
16560        mAttachInfo.mDisplayState = display.getState();
16561        onMovedToDisplay(display.getDisplayId(), config);
16562    }
16563
16564    /**
16565     * Called by the system when the hosting activity is moved from one display to another without
16566     * recreation. This means that the activity is declared to handle all changes to configuration
16567     * that happened when it was switched to another display, so it wasn't destroyed and created
16568     * again.
16569     *
16570     * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
16571     * applied configuration actually changed. It is up to app developer to choose whether to handle
16572     * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
16573     * call.
16574     *
16575     * <p>Use this callback to track changes to the displays if some functionality relies on an
16576     * association with some display properties.
16577     *
16578     * @param displayId The id of the display to which the view was moved.
16579     * @param config Configuration of the resources on new display after move.
16580     *
16581     * @see #onConfigurationChanged(Configuration)
16582     */
16583    public void onMovedToDisplay(int displayId, Configuration config) {
16584    }
16585
16586    /**
16587     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
16588     */
16589    private boolean hasRtlSupport() {
16590        return mContext.getApplicationInfo().hasRtlSupport();
16591    }
16592
16593    /**
16594     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
16595     * RTL not supported)
16596     */
16597    private boolean isRtlCompatibilityMode() {
16598        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
16599        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
16600    }
16601
16602    /**
16603     * @return true if RTL properties need resolution.
16604     *
16605     */
16606    private boolean needRtlPropertiesResolution() {
16607        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
16608    }
16609
16610    /**
16611     * Called when any RTL property (layout direction or text direction or text alignment) has
16612     * been changed.
16613     *
16614     * Subclasses need to override this method to take care of cached information that depends on the
16615     * resolved layout direction, or to inform child views that inherit their layout direction.
16616     *
16617     * The default implementation does nothing.
16618     *
16619     * @param layoutDirection the direction of the layout
16620     *
16621     * @see #LAYOUT_DIRECTION_LTR
16622     * @see #LAYOUT_DIRECTION_RTL
16623     */
16624    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
16625    }
16626
16627    /**
16628     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
16629     * that the parent directionality can and will be resolved before its children.
16630     *
16631     * @return true if resolution has been done, false otherwise.
16632     *
16633     * @hide
16634     */
16635    public boolean resolveLayoutDirection() {
16636        // Clear any previous layout direction resolution
16637        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16638
16639        if (hasRtlSupport()) {
16640            // Set resolved depending on layout direction
16641            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
16642                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
16643                case LAYOUT_DIRECTION_INHERIT:
16644                    // We cannot resolve yet. LTR is by default and let the resolution happen again
16645                    // later to get the correct resolved value
16646                    if (!canResolveLayoutDirection()) return false;
16647
16648                    // Parent has not yet resolved, LTR is still the default
16649                    try {
16650                        if (!mParent.isLayoutDirectionResolved()) return false;
16651
16652                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16653                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16654                        }
16655                    } catch (AbstractMethodError e) {
16656                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16657                                " does not fully implement ViewParent", e);
16658                    }
16659                    break;
16660                case LAYOUT_DIRECTION_RTL:
16661                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16662                    break;
16663                case LAYOUT_DIRECTION_LOCALE:
16664                    if((LAYOUT_DIRECTION_RTL ==
16665                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
16666                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
16667                    }
16668                    break;
16669                default:
16670                    // Nothing to do, LTR by default
16671            }
16672        }
16673
16674        // Set to resolved
16675        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16676        return true;
16677    }
16678
16679    /**
16680     * Check if layout direction resolution can be done.
16681     *
16682     * @return true if layout direction resolution can be done otherwise return false.
16683     */
16684    public boolean canResolveLayoutDirection() {
16685        switch (getRawLayoutDirection()) {
16686            case LAYOUT_DIRECTION_INHERIT:
16687                if (mParent != null) {
16688                    try {
16689                        return mParent.canResolveLayoutDirection();
16690                    } catch (AbstractMethodError e) {
16691                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
16692                                " does not fully implement ViewParent", e);
16693                    }
16694                }
16695                return false;
16696
16697            default:
16698                return true;
16699        }
16700    }
16701
16702    /**
16703     * Reset the resolved layout direction. Layout direction will be resolved during a call to
16704     * {@link #onMeasure(int, int)}.
16705     *
16706     * @hide
16707     */
16708    public void resetResolvedLayoutDirection() {
16709        // Reset the current resolved bits
16710        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
16711    }
16712
16713    /**
16714     * @return true if the layout direction is inherited.
16715     *
16716     * @hide
16717     */
16718    public boolean isLayoutDirectionInherited() {
16719        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
16720    }
16721
16722    /**
16723     * @return true if layout direction has been resolved.
16724     */
16725    public boolean isLayoutDirectionResolved() {
16726        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
16727    }
16728
16729    /**
16730     * Return if padding has been resolved
16731     *
16732     * @hide
16733     */
16734    boolean isPaddingResolved() {
16735        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
16736    }
16737
16738    /**
16739     * Resolves padding depending on layout direction, if applicable, and
16740     * recomputes internal padding values to adjust for scroll bars.
16741     *
16742     * @hide
16743     */
16744    public void resolvePadding() {
16745        final int resolvedLayoutDirection = getLayoutDirection();
16746
16747        if (!isRtlCompatibilityMode()) {
16748            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
16749            // If start / end padding are defined, they will be resolved (hence overriding) to
16750            // left / right or right / left depending on the resolved layout direction.
16751            // If start / end padding are not defined, use the left / right ones.
16752            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
16753                Rect padding = sThreadLocal.get();
16754                if (padding == null) {
16755                    padding = new Rect();
16756                    sThreadLocal.set(padding);
16757                }
16758                mBackground.getPadding(padding);
16759                if (!mLeftPaddingDefined) {
16760                    mUserPaddingLeftInitial = padding.left;
16761                }
16762                if (!mRightPaddingDefined) {
16763                    mUserPaddingRightInitial = padding.right;
16764                }
16765            }
16766            switch (resolvedLayoutDirection) {
16767                case LAYOUT_DIRECTION_RTL:
16768                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16769                        mUserPaddingRight = mUserPaddingStart;
16770                    } else {
16771                        mUserPaddingRight = mUserPaddingRightInitial;
16772                    }
16773                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16774                        mUserPaddingLeft = mUserPaddingEnd;
16775                    } else {
16776                        mUserPaddingLeft = mUserPaddingLeftInitial;
16777                    }
16778                    break;
16779                case LAYOUT_DIRECTION_LTR:
16780                default:
16781                    if (mUserPaddingStart != UNDEFINED_PADDING) {
16782                        mUserPaddingLeft = mUserPaddingStart;
16783                    } else {
16784                        mUserPaddingLeft = mUserPaddingLeftInitial;
16785                    }
16786                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
16787                        mUserPaddingRight = mUserPaddingEnd;
16788                    } else {
16789                        mUserPaddingRight = mUserPaddingRightInitial;
16790                    }
16791            }
16792
16793            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
16794        }
16795
16796        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16797        onRtlPropertiesChanged(resolvedLayoutDirection);
16798
16799        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
16800    }
16801
16802    /**
16803     * Reset the resolved layout direction.
16804     *
16805     * @hide
16806     */
16807    public void resetResolvedPadding() {
16808        resetResolvedPaddingInternal();
16809    }
16810
16811    /**
16812     * Used when we only want to reset *this* view's padding and not trigger overrides
16813     * in ViewGroup that reset children too.
16814     */
16815    void resetResolvedPaddingInternal() {
16816        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
16817    }
16818
16819    /**
16820     * This is called when the view is detached from a window.  At this point it
16821     * no longer has a surface for drawing.
16822     *
16823     * @see #onAttachedToWindow()
16824     */
16825    @CallSuper
16826    protected void onDetachedFromWindow() {
16827    }
16828
16829    /**
16830     * This is a framework-internal mirror of onDetachedFromWindow() that's called
16831     * after onDetachedFromWindow().
16832     *
16833     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
16834     * The super method should be called at the end of the overridden method to ensure
16835     * subclasses are destroyed first
16836     *
16837     * @hide
16838     */
16839    @CallSuper
16840    protected void onDetachedFromWindowInternal() {
16841        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
16842        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16843        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
16844
16845        removeUnsetPressCallback();
16846        removeLongPressCallback();
16847        removePerformClickCallback();
16848        removeSendViewScrolledAccessibilityEventCallback();
16849        stopNestedScroll();
16850
16851        // Anything that started animating right before detach should already
16852        // be in its final state when re-attached.
16853        jumpDrawablesToCurrentState();
16854
16855        destroyDrawingCache();
16856
16857        cleanupDraw();
16858        mCurrentAnimation = null;
16859
16860        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
16861            hideTooltip();
16862        }
16863    }
16864
16865    private void cleanupDraw() {
16866        resetDisplayList();
16867        if (mAttachInfo != null) {
16868            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
16869        }
16870    }
16871
16872    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
16873    }
16874
16875    /**
16876     * @return The number of times this view has been attached to a window
16877     */
16878    protected int getWindowAttachCount() {
16879        return mWindowAttachCount;
16880    }
16881
16882    /**
16883     * Retrieve a unique token identifying the window this view is attached to.
16884     * @return Return the window's token for use in
16885     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
16886     */
16887    public IBinder getWindowToken() {
16888        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
16889    }
16890
16891    /**
16892     * Retrieve the {@link WindowId} for the window this view is
16893     * currently attached to.
16894     */
16895    public WindowId getWindowId() {
16896        if (mAttachInfo == null) {
16897            return null;
16898        }
16899        if (mAttachInfo.mWindowId == null) {
16900            try {
16901                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
16902                        mAttachInfo.mWindowToken);
16903                mAttachInfo.mWindowId = new WindowId(
16904                        mAttachInfo.mIWindowId);
16905            } catch (RemoteException e) {
16906            }
16907        }
16908        return mAttachInfo.mWindowId;
16909    }
16910
16911    /**
16912     * Retrieve a unique token identifying the top-level "real" window of
16913     * the window that this view is attached to.  That is, this is like
16914     * {@link #getWindowToken}, except if the window this view in is a panel
16915     * window (attached to another containing window), then the token of
16916     * the containing window is returned instead.
16917     *
16918     * @return Returns the associated window token, either
16919     * {@link #getWindowToken()} or the containing window's token.
16920     */
16921    public IBinder getApplicationWindowToken() {
16922        AttachInfo ai = mAttachInfo;
16923        if (ai != null) {
16924            IBinder appWindowToken = ai.mPanelParentWindowToken;
16925            if (appWindowToken == null) {
16926                appWindowToken = ai.mWindowToken;
16927            }
16928            return appWindowToken;
16929        }
16930        return null;
16931    }
16932
16933    /**
16934     * Gets the logical display to which the view's window has been attached.
16935     *
16936     * @return The logical display, or null if the view is not currently attached to a window.
16937     */
16938    public Display getDisplay() {
16939        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
16940    }
16941
16942    /**
16943     * Retrieve private session object this view hierarchy is using to
16944     * communicate with the window manager.
16945     * @return the session object to communicate with the window manager
16946     */
16947    /*package*/ IWindowSession getWindowSession() {
16948        return mAttachInfo != null ? mAttachInfo.mSession : null;
16949    }
16950
16951    /**
16952     * Return the visibility value of the least visible component passed.
16953     */
16954    int combineVisibility(int vis1, int vis2) {
16955        // This works because VISIBLE < INVISIBLE < GONE.
16956        return Math.max(vis1, vis2);
16957    }
16958
16959    /**
16960     * @param info the {@link android.view.View.AttachInfo} to associated with
16961     *        this view
16962     */
16963    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
16964        mAttachInfo = info;
16965        if (mOverlay != null) {
16966            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
16967        }
16968        mWindowAttachCount++;
16969        // We will need to evaluate the drawable state at least once.
16970        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16971        if (mFloatingTreeObserver != null) {
16972            info.mTreeObserver.merge(mFloatingTreeObserver);
16973            mFloatingTreeObserver = null;
16974        }
16975
16976        registerPendingFrameMetricsObservers();
16977
16978        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
16979            mAttachInfo.mScrollContainers.add(this);
16980            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
16981        }
16982        // Transfer all pending runnables.
16983        if (mRunQueue != null) {
16984            mRunQueue.executeActions(info.mHandler);
16985            mRunQueue = null;
16986        }
16987        performCollectViewAttributes(mAttachInfo, visibility);
16988        onAttachedToWindow();
16989
16990        ListenerInfo li = mListenerInfo;
16991        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
16992                li != null ? li.mOnAttachStateChangeListeners : null;
16993        if (listeners != null && listeners.size() > 0) {
16994            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
16995            // perform the dispatching. The iterator is a safe guard against listeners that
16996            // could mutate the list by calling the various add/remove methods. This prevents
16997            // the array from being modified while we iterate it.
16998            for (OnAttachStateChangeListener listener : listeners) {
16999                listener.onViewAttachedToWindow(this);
17000            }
17001        }
17002
17003        int vis = info.mWindowVisibility;
17004        if (vis != GONE) {
17005            onWindowVisibilityChanged(vis);
17006            if (isShown()) {
17007                // Calling onVisibilityAggregated directly here since the subtree will also
17008                // receive dispatchAttachedToWindow and this same call
17009                onVisibilityAggregated(vis == VISIBLE);
17010            }
17011        }
17012
17013        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
17014        // As all views in the subtree will already receive dispatchAttachedToWindow
17015        // traversing the subtree again here is not desired.
17016        onVisibilityChanged(this, visibility);
17017
17018        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
17019            // If nobody has evaluated the drawable state yet, then do it now.
17020            refreshDrawableState();
17021        }
17022        needGlobalAttributesUpdate(false);
17023
17024        notifyEnterOrExitForAutoFillIfNeeded(true);
17025    }
17026
17027    void dispatchDetachedFromWindow() {
17028        AttachInfo info = mAttachInfo;
17029        if (info != null) {
17030            int vis = info.mWindowVisibility;
17031            if (vis != GONE) {
17032                onWindowVisibilityChanged(GONE);
17033                if (isShown()) {
17034                    // Invoking onVisibilityAggregated directly here since the subtree
17035                    // will also receive detached from window
17036                    onVisibilityAggregated(false);
17037                }
17038            }
17039        }
17040
17041        onDetachedFromWindow();
17042        onDetachedFromWindowInternal();
17043
17044        InputMethodManager imm = InputMethodManager.peekInstance();
17045        if (imm != null) {
17046            imm.onViewDetachedFromWindow(this);
17047        }
17048
17049        ListenerInfo li = mListenerInfo;
17050        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17051                li != null ? li.mOnAttachStateChangeListeners : null;
17052        if (listeners != null && listeners.size() > 0) {
17053            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17054            // perform the dispatching. The iterator is a safe guard against listeners that
17055            // could mutate the list by calling the various add/remove methods. This prevents
17056            // the array from being modified while we iterate it.
17057            for (OnAttachStateChangeListener listener : listeners) {
17058                listener.onViewDetachedFromWindow(this);
17059            }
17060        }
17061
17062        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
17063            mAttachInfo.mScrollContainers.remove(this);
17064            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
17065        }
17066
17067        mAttachInfo = null;
17068        if (mOverlay != null) {
17069            mOverlay.getOverlayView().dispatchDetachedFromWindow();
17070        }
17071
17072        notifyEnterOrExitForAutoFillIfNeeded(false);
17073    }
17074
17075    /**
17076     * Cancel any deferred high-level input events that were previously posted to the event queue.
17077     *
17078     * <p>Many views post high-level events such as click handlers to the event queue
17079     * to run deferred in order to preserve a desired user experience - clearing visible
17080     * pressed states before executing, etc. This method will abort any events of this nature
17081     * that are currently in flight.</p>
17082     *
17083     * <p>Custom views that generate their own high-level deferred input events should override
17084     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
17085     *
17086     * <p>This will also cancel pending input events for any child views.</p>
17087     *
17088     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
17089     * This will not impact newer events posted after this call that may occur as a result of
17090     * lower-level input events still waiting in the queue. If you are trying to prevent
17091     * double-submitted  events for the duration of some sort of asynchronous transaction
17092     * you should also take other steps to protect against unexpected double inputs e.g. calling
17093     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
17094     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
17095     */
17096    public final void cancelPendingInputEvents() {
17097        dispatchCancelPendingInputEvents();
17098    }
17099
17100    /**
17101     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17102     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17103     */
17104    void dispatchCancelPendingInputEvents() {
17105        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17106        onCancelPendingInputEvents();
17107        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17108            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17109                    " did not call through to super.onCancelPendingInputEvents()");
17110        }
17111    }
17112
17113    /**
17114     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17115     * a parent view.
17116     *
17117     * <p>This method is responsible for removing any pending high-level input events that were
17118     * posted to the event queue to run later. Custom view classes that post their own deferred
17119     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17120     * {@link android.os.Handler} should override this method, call
17121     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17122     * </p>
17123     */
17124    public void onCancelPendingInputEvents() {
17125        removePerformClickCallback();
17126        cancelLongPress();
17127        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17128    }
17129
17130    /**
17131     * Store this view hierarchy's frozen state into the given container.
17132     *
17133     * @param container The SparseArray in which to save the view's state.
17134     *
17135     * @see #restoreHierarchyState(android.util.SparseArray)
17136     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17137     * @see #onSaveInstanceState()
17138     */
17139    public void saveHierarchyState(SparseArray<Parcelable> container) {
17140        dispatchSaveInstanceState(container);
17141    }
17142
17143    /**
17144     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17145     * this view and its children. May be overridden to modify how freezing happens to a
17146     * view's children; for example, some views may want to not store state for their children.
17147     *
17148     * @param container The SparseArray in which to save the view's state.
17149     *
17150     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17151     * @see #saveHierarchyState(android.util.SparseArray)
17152     * @see #onSaveInstanceState()
17153     */
17154    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17155        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17156            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17157            Parcelable state = onSaveInstanceState();
17158            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17159                throw new IllegalStateException(
17160                        "Derived class did not call super.onSaveInstanceState()");
17161            }
17162            if (state != null) {
17163                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17164                // + ": " + state);
17165                container.put(mID, state);
17166            }
17167        }
17168    }
17169
17170    /**
17171     * Hook allowing a view to generate a representation of its internal state
17172     * that can later be used to create a new instance with that same state.
17173     * This state should only contain information that is not persistent or can
17174     * not be reconstructed later. For example, you will never store your
17175     * current position on screen because that will be computed again when a
17176     * new instance of the view is placed in its view hierarchy.
17177     * <p>
17178     * Some examples of things you may store here: the current cursor position
17179     * in a text view (but usually not the text itself since that is stored in a
17180     * content provider or other persistent storage), the currently selected
17181     * item in a list view.
17182     *
17183     * @return Returns a Parcelable object containing the view's current dynamic
17184     *         state, or null if there is nothing interesting to save. The
17185     *         default implementation returns null.
17186     * @see #onRestoreInstanceState(android.os.Parcelable)
17187     * @see #saveHierarchyState(android.util.SparseArray)
17188     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17189     * @see #setSaveEnabled(boolean)
17190     */
17191    @CallSuper
17192    protected Parcelable onSaveInstanceState() {
17193        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17194        if (mStartActivityRequestWho != null || isAutofilled()
17195                || mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17196            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17197
17198            if (mStartActivityRequestWho != null) {
17199                state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
17200            }
17201
17202            if (isAutofilled()) {
17203                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
17204            }
17205
17206            if (mAccessibilityViewId > LAST_APP_ACCESSIBILITY_ID) {
17207                state.mSavedData |= BaseSavedState.ACCESSIBILITY_ID;
17208            }
17209
17210            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17211            state.mIsAutofilled = isAutofilled();
17212            state.mAccessibilityViewId = mAccessibilityViewId;
17213            return state;
17214        }
17215        return BaseSavedState.EMPTY_STATE;
17216    }
17217
17218    /**
17219     * Restore this view hierarchy's frozen state from the given container.
17220     *
17221     * @param container The SparseArray which holds previously frozen states.
17222     *
17223     * @see #saveHierarchyState(android.util.SparseArray)
17224     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17225     * @see #onRestoreInstanceState(android.os.Parcelable)
17226     */
17227    public void restoreHierarchyState(SparseArray<Parcelable> container) {
17228        dispatchRestoreInstanceState(container);
17229    }
17230
17231    /**
17232     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17233     * state for this view and its children. May be overridden to modify how restoring
17234     * happens to a view's children; for example, some views may want to not store state
17235     * for their children.
17236     *
17237     * @param container The SparseArray which holds previously saved state.
17238     *
17239     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17240     * @see #restoreHierarchyState(android.util.SparseArray)
17241     * @see #onRestoreInstanceState(android.os.Parcelable)
17242     */
17243    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17244        if (mID != NO_ID) {
17245            Parcelable state = container.get(mID);
17246            if (state != null) {
17247                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17248                // + ": " + state);
17249                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17250                onRestoreInstanceState(state);
17251                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17252                    throw new IllegalStateException(
17253                            "Derived class did not call super.onRestoreInstanceState()");
17254                }
17255            }
17256        }
17257    }
17258
17259    /**
17260     * Hook allowing a view to re-apply a representation of its internal state that had previously
17261     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17262     * null state.
17263     *
17264     * @param state The frozen state that had previously been returned by
17265     *        {@link #onSaveInstanceState}.
17266     *
17267     * @see #onSaveInstanceState()
17268     * @see #restoreHierarchyState(android.util.SparseArray)
17269     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17270     */
17271    @CallSuper
17272    protected void onRestoreInstanceState(Parcelable state) {
17273        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17274        if (state != null && !(state instanceof AbsSavedState)) {
17275            throw new IllegalArgumentException("Wrong state class, expecting View State but "
17276                    + "received " + state.getClass().toString() + " instead. This usually happens "
17277                    + "when two views of different type have the same id in the same hierarchy. "
17278                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17279                    + "other views do not use the same id.");
17280        }
17281        if (state != null && state instanceof BaseSavedState) {
17282            BaseSavedState baseState = (BaseSavedState) state;
17283
17284            if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
17285                mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
17286            }
17287            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
17288                setAutofilled(baseState.mIsAutofilled);
17289            }
17290            if ((baseState.mSavedData & BaseSavedState.ACCESSIBILITY_ID) != 0) {
17291                mAccessibilityViewId = baseState.mAccessibilityViewId;
17292            }
17293        }
17294    }
17295
17296    /**
17297     * <p>Return the time at which the drawing of the view hierarchy started.</p>
17298     *
17299     * @return the drawing start time in milliseconds
17300     */
17301    public long getDrawingTime() {
17302        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17303    }
17304
17305    /**
17306     * <p>Enables or disables the duplication of the parent's state into this view. When
17307     * duplication is enabled, this view gets its drawable state from its parent rather
17308     * than from its own internal properties.</p>
17309     *
17310     * <p>Note: in the current implementation, setting this property to true after the
17311     * view was added to a ViewGroup might have no effect at all. This property should
17312     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17313     *
17314     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17315     * property is enabled, an exception will be thrown.</p>
17316     *
17317     * <p>Note: if the child view uses and updates additional states which are unknown to the
17318     * parent, these states should not be affected by this method.</p>
17319     *
17320     * @param enabled True to enable duplication of the parent's drawable state, false
17321     *                to disable it.
17322     *
17323     * @see #getDrawableState()
17324     * @see #isDuplicateParentStateEnabled()
17325     */
17326    public void setDuplicateParentStateEnabled(boolean enabled) {
17327        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17328    }
17329
17330    /**
17331     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17332     *
17333     * @return True if this view's drawable state is duplicated from the parent,
17334     *         false otherwise
17335     *
17336     * @see #getDrawableState()
17337     * @see #setDuplicateParentStateEnabled(boolean)
17338     */
17339    public boolean isDuplicateParentStateEnabled() {
17340        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17341    }
17342
17343    /**
17344     * <p>Specifies the type of layer backing this view. The layer can be
17345     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17346     * {@link #LAYER_TYPE_HARDWARE}.</p>
17347     *
17348     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17349     * instance that controls how the layer is composed on screen. The following
17350     * properties of the paint are taken into account when composing the layer:</p>
17351     * <ul>
17352     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17353     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17354     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17355     * </ul>
17356     *
17357     * <p>If this view has an alpha value set to < 1.0 by calling
17358     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17359     * by this view's alpha value.</p>
17360     *
17361     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17362     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17363     * for more information on when and how to use layers.</p>
17364     *
17365     * @param layerType The type of layer to use with this view, must be one of
17366     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17367     *        {@link #LAYER_TYPE_HARDWARE}
17368     * @param paint The paint used to compose the layer. This argument is optional
17369     *        and can be null. It is ignored when the layer type is
17370     *        {@link #LAYER_TYPE_NONE}
17371     *
17372     * @see #getLayerType()
17373     * @see #LAYER_TYPE_NONE
17374     * @see #LAYER_TYPE_SOFTWARE
17375     * @see #LAYER_TYPE_HARDWARE
17376     * @see #setAlpha(float)
17377     *
17378     * @attr ref android.R.styleable#View_layerType
17379     */
17380    public void setLayerType(int layerType, @Nullable Paint paint) {
17381        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17382            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17383                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17384        }
17385
17386        boolean typeChanged = mRenderNode.setLayerType(layerType);
17387
17388        if (!typeChanged) {
17389            setLayerPaint(paint);
17390            return;
17391        }
17392
17393        if (layerType != LAYER_TYPE_SOFTWARE) {
17394            // Destroy any previous software drawing cache if present
17395            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17396            // drawing cache created in View#draw when drawing to a SW canvas.
17397            destroyDrawingCache();
17398        }
17399
17400        mLayerType = layerType;
17401        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17402        mRenderNode.setLayerPaint(mLayerPaint);
17403
17404        // draw() behaves differently if we are on a layer, so we need to
17405        // invalidate() here
17406        invalidateParentCaches();
17407        invalidate(true);
17408    }
17409
17410    /**
17411     * Updates the {@link Paint} object used with the current layer (used only if the current
17412     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17413     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17414     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17415     * ensure that the view gets redrawn immediately.
17416     *
17417     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17418     * instance that controls how the layer is composed on screen. The following
17419     * properties of the paint are taken into account when composing the layer:</p>
17420     * <ul>
17421     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17422     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17423     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17424     * </ul>
17425     *
17426     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17427     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17428     *
17429     * @param paint The paint used to compose the layer. This argument is optional
17430     *        and can be null. It is ignored when the layer type is
17431     *        {@link #LAYER_TYPE_NONE}
17432     *
17433     * @see #setLayerType(int, android.graphics.Paint)
17434     */
17435    public void setLayerPaint(@Nullable Paint paint) {
17436        int layerType = getLayerType();
17437        if (layerType != LAYER_TYPE_NONE) {
17438            mLayerPaint = paint;
17439            if (layerType == LAYER_TYPE_HARDWARE) {
17440                if (mRenderNode.setLayerPaint(paint)) {
17441                    invalidateViewProperty(false, false);
17442                }
17443            } else {
17444                invalidate();
17445            }
17446        }
17447    }
17448
17449    /**
17450     * Indicates what type of layer is currently associated with this view. By default
17451     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17452     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17453     * for more information on the different types of layers.
17454     *
17455     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17456     *         {@link #LAYER_TYPE_HARDWARE}
17457     *
17458     * @see #setLayerType(int, android.graphics.Paint)
17459     * @see #buildLayer()
17460     * @see #LAYER_TYPE_NONE
17461     * @see #LAYER_TYPE_SOFTWARE
17462     * @see #LAYER_TYPE_HARDWARE
17463     */
17464    public int getLayerType() {
17465        return mLayerType;
17466    }
17467
17468    /**
17469     * Forces this view's layer to be created and this view to be rendered
17470     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17471     * invoking this method will have no effect.
17472     *
17473     * This method can for instance be used to render a view into its layer before
17474     * starting an animation. If this view is complex, rendering into the layer
17475     * before starting the animation will avoid skipping frames.
17476     *
17477     * @throws IllegalStateException If this view is not attached to a window
17478     *
17479     * @see #setLayerType(int, android.graphics.Paint)
17480     */
17481    public void buildLayer() {
17482        if (mLayerType == LAYER_TYPE_NONE) return;
17483
17484        final AttachInfo attachInfo = mAttachInfo;
17485        if (attachInfo == null) {
17486            throw new IllegalStateException("This view must be attached to a window first");
17487        }
17488
17489        if (getWidth() == 0 || getHeight() == 0) {
17490            return;
17491        }
17492
17493        switch (mLayerType) {
17494            case LAYER_TYPE_HARDWARE:
17495                updateDisplayListIfDirty();
17496                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17497                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17498                }
17499                break;
17500            case LAYER_TYPE_SOFTWARE:
17501                buildDrawingCache(true);
17502                break;
17503        }
17504    }
17505
17506    /**
17507     * Destroys all hardware rendering resources. This method is invoked
17508     * when the system needs to reclaim resources. Upon execution of this
17509     * method, you should free any OpenGL resources created by the view.
17510     *
17511     * Note: you <strong>must</strong> call
17512     * <code>super.destroyHardwareResources()</code> when overriding
17513     * this method.
17514     *
17515     * @hide
17516     */
17517    @CallSuper
17518    protected void destroyHardwareResources() {
17519        if (mOverlay != null) {
17520            mOverlay.getOverlayView().destroyHardwareResources();
17521        }
17522        if (mGhostView != null) {
17523            mGhostView.destroyHardwareResources();
17524        }
17525    }
17526
17527    /**
17528     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17529     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17530     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17531     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17532     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17533     * null.</p>
17534     *
17535     * <p>Enabling the drawing cache is similar to
17536     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17537     * acceleration is turned off. When hardware acceleration is turned on, enabling the
17538     * drawing cache has no effect on rendering because the system uses a different mechanism
17539     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
17540     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
17541     * for information on how to enable software and hardware layers.</p>
17542     *
17543     * <p>This API can be used to manually generate
17544     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
17545     * {@link #getDrawingCache()}.</p>
17546     *
17547     * @param enabled true to enable the drawing cache, false otherwise
17548     *
17549     * @see #isDrawingCacheEnabled()
17550     * @see #getDrawingCache()
17551     * @see #buildDrawingCache()
17552     * @see #setLayerType(int, android.graphics.Paint)
17553     */
17554    public void setDrawingCacheEnabled(boolean enabled) {
17555        mCachingFailed = false;
17556        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
17557    }
17558
17559    /**
17560     * <p>Indicates whether the drawing cache is enabled for this view.</p>
17561     *
17562     * @return true if the drawing cache is enabled
17563     *
17564     * @see #setDrawingCacheEnabled(boolean)
17565     * @see #getDrawingCache()
17566     */
17567    @ViewDebug.ExportedProperty(category = "drawing")
17568    public boolean isDrawingCacheEnabled() {
17569        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
17570    }
17571
17572    /**
17573     * Debugging utility which recursively outputs the dirty state of a view and its
17574     * descendants.
17575     *
17576     * @hide
17577     */
17578    @SuppressWarnings({"UnusedDeclaration"})
17579    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
17580        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
17581                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
17582                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
17583                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
17584        if (clear) {
17585            mPrivateFlags &= clearMask;
17586        }
17587        if (this instanceof ViewGroup) {
17588            ViewGroup parent = (ViewGroup) this;
17589            final int count = parent.getChildCount();
17590            for (int i = 0; i < count; i++) {
17591                final View child = parent.getChildAt(i);
17592                child.outputDirtyFlags(indent + "  ", clear, clearMask);
17593            }
17594        }
17595    }
17596
17597    /**
17598     * This method is used by ViewGroup to cause its children to restore or recreate their
17599     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
17600     * to recreate its own display list, which would happen if it went through the normal
17601     * draw/dispatchDraw mechanisms.
17602     *
17603     * @hide
17604     */
17605    protected void dispatchGetDisplayList() {}
17606
17607    /**
17608     * A view that is not attached or hardware accelerated cannot create a display list.
17609     * This method checks these conditions and returns the appropriate result.
17610     *
17611     * @return true if view has the ability to create a display list, false otherwise.
17612     *
17613     * @hide
17614     */
17615    public boolean canHaveDisplayList() {
17616        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
17617    }
17618
17619    /**
17620     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
17621     * @hide
17622     */
17623    @NonNull
17624    public RenderNode updateDisplayListIfDirty() {
17625        final RenderNode renderNode = mRenderNode;
17626        if (!canHaveDisplayList()) {
17627            // can't populate RenderNode, don't try
17628            return renderNode;
17629        }
17630
17631        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
17632                || !renderNode.isValid()
17633                || (mRecreateDisplayList)) {
17634            // Don't need to recreate the display list, just need to tell our
17635            // children to restore/recreate theirs
17636            if (renderNode.isValid()
17637                    && !mRecreateDisplayList) {
17638                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17639                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17640                dispatchGetDisplayList();
17641
17642                return renderNode; // no work needed
17643            }
17644
17645            // If we got here, we're recreating it. Mark it as such to ensure that
17646            // we copy in child display lists into ours in drawChild()
17647            mRecreateDisplayList = true;
17648
17649            int width = mRight - mLeft;
17650            int height = mBottom - mTop;
17651            int layerType = getLayerType();
17652
17653            final DisplayListCanvas canvas = renderNode.start(width, height);
17654            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
17655
17656            try {
17657                if (layerType == LAYER_TYPE_SOFTWARE) {
17658                    buildDrawingCache(true);
17659                    Bitmap cache = getDrawingCache(true);
17660                    if (cache != null) {
17661                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
17662                    }
17663                } else {
17664                    computeScroll();
17665
17666                    canvas.translate(-mScrollX, -mScrollY);
17667                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17668                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17669
17670                    // Fast path for layouts with no backgrounds
17671                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17672                        dispatchDraw(canvas);
17673                        drawAutofilledHighlight(canvas);
17674                        if (mOverlay != null && !mOverlay.isEmpty()) {
17675                            mOverlay.getOverlayView().draw(canvas);
17676                        }
17677                        if (debugDraw()) {
17678                            debugDrawFocus(canvas);
17679                        }
17680                    } else {
17681                        draw(canvas);
17682                    }
17683                }
17684            } finally {
17685                renderNode.end(canvas);
17686                setDisplayListProperties(renderNode);
17687            }
17688        } else {
17689            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
17690            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17691        }
17692        return renderNode;
17693    }
17694
17695    private void resetDisplayList() {
17696        mRenderNode.discardDisplayList();
17697        if (mBackgroundRenderNode != null) {
17698            mBackgroundRenderNode.discardDisplayList();
17699        }
17700    }
17701
17702    /**
17703     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
17704     *
17705     * @return A non-scaled bitmap representing this view or null if cache is disabled.
17706     *
17707     * @see #getDrawingCache(boolean)
17708     */
17709    public Bitmap getDrawingCache() {
17710        return getDrawingCache(false);
17711    }
17712
17713    /**
17714     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
17715     * is null when caching is disabled. If caching is enabled and the cache is not ready,
17716     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
17717     * draw from the cache when the cache is enabled. To benefit from the cache, you must
17718     * request the drawing cache by calling this method and draw it on screen if the
17719     * returned bitmap is not null.</p>
17720     *
17721     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17722     * this method will create a bitmap of the same size as this view. Because this bitmap
17723     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17724     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17725     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17726     * size than the view. This implies that your application must be able to handle this
17727     * size.</p>
17728     *
17729     * @param autoScale Indicates whether the generated bitmap should be scaled based on
17730     *        the current density of the screen when the application is in compatibility
17731     *        mode.
17732     *
17733     * @return A bitmap representing this view or null if cache is disabled.
17734     *
17735     * @see #setDrawingCacheEnabled(boolean)
17736     * @see #isDrawingCacheEnabled()
17737     * @see #buildDrawingCache(boolean)
17738     * @see #destroyDrawingCache()
17739     */
17740    public Bitmap getDrawingCache(boolean autoScale) {
17741        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
17742            return null;
17743        }
17744        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
17745            buildDrawingCache(autoScale);
17746        }
17747        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
17748    }
17749
17750    /**
17751     * <p>Frees the resources used by the drawing cache. If you call
17752     * {@link #buildDrawingCache()} manually without calling
17753     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17754     * should cleanup the cache with this method afterwards.</p>
17755     *
17756     * @see #setDrawingCacheEnabled(boolean)
17757     * @see #buildDrawingCache()
17758     * @see #getDrawingCache()
17759     */
17760    public void destroyDrawingCache() {
17761        if (mDrawingCache != null) {
17762            mDrawingCache.recycle();
17763            mDrawingCache = null;
17764        }
17765        if (mUnscaledDrawingCache != null) {
17766            mUnscaledDrawingCache.recycle();
17767            mUnscaledDrawingCache = null;
17768        }
17769    }
17770
17771    /**
17772     * Setting a solid background color for the drawing cache's bitmaps will improve
17773     * performance and memory usage. Note, though that this should only be used if this
17774     * view will always be drawn on top of a solid color.
17775     *
17776     * @param color The background color to use for the drawing cache's bitmap
17777     *
17778     * @see #setDrawingCacheEnabled(boolean)
17779     * @see #buildDrawingCache()
17780     * @see #getDrawingCache()
17781     */
17782    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
17783        if (color != mDrawingCacheBackgroundColor) {
17784            mDrawingCacheBackgroundColor = color;
17785            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
17786        }
17787    }
17788
17789    /**
17790     * @see #setDrawingCacheBackgroundColor(int)
17791     *
17792     * @return The background color to used for the drawing cache's bitmap
17793     */
17794    @ColorInt
17795    public int getDrawingCacheBackgroundColor() {
17796        return mDrawingCacheBackgroundColor;
17797    }
17798
17799    /**
17800     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
17801     *
17802     * @see #buildDrawingCache(boolean)
17803     */
17804    public void buildDrawingCache() {
17805        buildDrawingCache(false);
17806    }
17807
17808    /**
17809     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
17810     *
17811     * <p>If you call {@link #buildDrawingCache()} manually without calling
17812     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
17813     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
17814     *
17815     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
17816     * this method will create a bitmap of the same size as this view. Because this bitmap
17817     * will be drawn scaled by the parent ViewGroup, the result on screen might show
17818     * scaling artifacts. To avoid such artifacts, you should call this method by setting
17819     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
17820     * size than the view. This implies that your application must be able to handle this
17821     * size.</p>
17822     *
17823     * <p>You should avoid calling this method when hardware acceleration is enabled. If
17824     * you do not need the drawing cache bitmap, calling this method will increase memory
17825     * usage and cause the view to be rendered in software once, thus negatively impacting
17826     * performance.</p>
17827     *
17828     * @see #getDrawingCache()
17829     * @see #destroyDrawingCache()
17830     */
17831    public void buildDrawingCache(boolean autoScale) {
17832        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
17833                mDrawingCache == null : mUnscaledDrawingCache == null)) {
17834            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
17835                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
17836                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
17837            }
17838            try {
17839                buildDrawingCacheImpl(autoScale);
17840            } finally {
17841                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
17842            }
17843        }
17844    }
17845
17846    /**
17847     * private, internal implementation of buildDrawingCache, used to enable tracing
17848     */
17849    private void buildDrawingCacheImpl(boolean autoScale) {
17850        mCachingFailed = false;
17851
17852        int width = mRight - mLeft;
17853        int height = mBottom - mTop;
17854
17855        final AttachInfo attachInfo = mAttachInfo;
17856        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
17857
17858        if (autoScale && scalingRequired) {
17859            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
17860            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
17861        }
17862
17863        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
17864        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
17865        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
17866
17867        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
17868        final long drawingCacheSize =
17869                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
17870        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
17871            if (width > 0 && height > 0) {
17872                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
17873                        + " too large to fit into a software layer (or drawing cache), needs "
17874                        + projectedBitmapSize + " bytes, only "
17875                        + drawingCacheSize + " available");
17876            }
17877            destroyDrawingCache();
17878            mCachingFailed = true;
17879            return;
17880        }
17881
17882        boolean clear = true;
17883        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
17884
17885        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
17886            Bitmap.Config quality;
17887            if (!opaque) {
17888                // Never pick ARGB_4444 because it looks awful
17889                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
17890                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
17891                    case DRAWING_CACHE_QUALITY_AUTO:
17892                    case DRAWING_CACHE_QUALITY_LOW:
17893                    case DRAWING_CACHE_QUALITY_HIGH:
17894                    default:
17895                        quality = Bitmap.Config.ARGB_8888;
17896                        break;
17897                }
17898            } else {
17899                // Optimization for translucent windows
17900                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
17901                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
17902            }
17903
17904            // Try to cleanup memory
17905            if (bitmap != null) bitmap.recycle();
17906
17907            try {
17908                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
17909                        width, height, quality);
17910                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
17911                if (autoScale) {
17912                    mDrawingCache = bitmap;
17913                } else {
17914                    mUnscaledDrawingCache = bitmap;
17915                }
17916                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
17917            } catch (OutOfMemoryError e) {
17918                // If there is not enough memory to create the bitmap cache, just
17919                // ignore the issue as bitmap caches are not required to draw the
17920                // view hierarchy
17921                if (autoScale) {
17922                    mDrawingCache = null;
17923                } else {
17924                    mUnscaledDrawingCache = null;
17925                }
17926                mCachingFailed = true;
17927                return;
17928            }
17929
17930            clear = drawingCacheBackgroundColor != 0;
17931        }
17932
17933        Canvas canvas;
17934        if (attachInfo != null) {
17935            canvas = attachInfo.mCanvas;
17936            if (canvas == null) {
17937                canvas = new Canvas();
17938            }
17939            canvas.setBitmap(bitmap);
17940            // Temporarily clobber the cached Canvas in case one of our children
17941            // is also using a drawing cache. Without this, the children would
17942            // steal the canvas by attaching their own bitmap to it and bad, bad
17943            // thing would happen (invisible views, corrupted drawings, etc.)
17944            attachInfo.mCanvas = null;
17945        } else {
17946            // This case should hopefully never or seldom happen
17947            canvas = new Canvas(bitmap);
17948        }
17949
17950        if (clear) {
17951            bitmap.eraseColor(drawingCacheBackgroundColor);
17952        }
17953
17954        computeScroll();
17955        final int restoreCount = canvas.save();
17956
17957        if (autoScale && scalingRequired) {
17958            final float scale = attachInfo.mApplicationScale;
17959            canvas.scale(scale, scale);
17960        }
17961
17962        canvas.translate(-mScrollX, -mScrollY);
17963
17964        mPrivateFlags |= PFLAG_DRAWN;
17965        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
17966                mLayerType != LAYER_TYPE_NONE) {
17967            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
17968        }
17969
17970        // Fast path for layouts with no backgrounds
17971        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
17972            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
17973            dispatchDraw(canvas);
17974            drawAutofilledHighlight(canvas);
17975            if (mOverlay != null && !mOverlay.isEmpty()) {
17976                mOverlay.getOverlayView().draw(canvas);
17977            }
17978        } else {
17979            draw(canvas);
17980        }
17981
17982        canvas.restoreToCount(restoreCount);
17983        canvas.setBitmap(null);
17984
17985        if (attachInfo != null) {
17986            // Restore the cached Canvas for our siblings
17987            attachInfo.mCanvas = canvas;
17988        }
17989    }
17990
17991    /**
17992     * Create a snapshot of the view into a bitmap.  We should probably make
17993     * some form of this public, but should think about the API.
17994     *
17995     * @hide
17996     */
17997    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
17998        int width = mRight - mLeft;
17999        int height = mBottom - mTop;
18000
18001        final AttachInfo attachInfo = mAttachInfo;
18002        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
18003        width = (int) ((width * scale) + 0.5f);
18004        height = (int) ((height * scale) + 0.5f);
18005
18006        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18007                width > 0 ? width : 1, height > 0 ? height : 1, quality);
18008        if (bitmap == null) {
18009            throw new OutOfMemoryError();
18010        }
18011
18012        Resources resources = getResources();
18013        if (resources != null) {
18014            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
18015        }
18016
18017        Canvas canvas;
18018        if (attachInfo != null) {
18019            canvas = attachInfo.mCanvas;
18020            if (canvas == null) {
18021                canvas = new Canvas();
18022            }
18023            canvas.setBitmap(bitmap);
18024            // Temporarily clobber the cached Canvas in case one of our children
18025            // is also using a drawing cache. Without this, the children would
18026            // steal the canvas by attaching their own bitmap to it and bad, bad
18027            // things would happen (invisible views, corrupted drawings, etc.)
18028            attachInfo.mCanvas = null;
18029        } else {
18030            // This case should hopefully never or seldom happen
18031            canvas = new Canvas(bitmap);
18032        }
18033        boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
18034        canvas.setHwBitmapsInSwModeEnabled(true);
18035        if ((backgroundColor & 0xff000000) != 0) {
18036            bitmap.eraseColor(backgroundColor);
18037        }
18038
18039        computeScroll();
18040        final int restoreCount = canvas.save();
18041        canvas.scale(scale, scale);
18042        canvas.translate(-mScrollX, -mScrollY);
18043
18044        // Temporarily remove the dirty mask
18045        int flags = mPrivateFlags;
18046        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18047
18048        // Fast path for layouts with no backgrounds
18049        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18050            dispatchDraw(canvas);
18051            drawAutofilledHighlight(canvas);
18052            if (mOverlay != null && !mOverlay.isEmpty()) {
18053                mOverlay.getOverlayView().draw(canvas);
18054            }
18055        } else {
18056            draw(canvas);
18057        }
18058
18059        mPrivateFlags = flags;
18060
18061        canvas.restoreToCount(restoreCount);
18062        canvas.setBitmap(null);
18063        canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
18064
18065        if (attachInfo != null) {
18066            // Restore the cached Canvas for our siblings
18067            attachInfo.mCanvas = canvas;
18068        }
18069
18070        return bitmap;
18071    }
18072
18073    /**
18074     * Indicates whether this View is currently in edit mode. A View is usually
18075     * in edit mode when displayed within a developer tool. For instance, if
18076     * this View is being drawn by a visual user interface builder, this method
18077     * should return true.
18078     *
18079     * Subclasses should check the return value of this method to provide
18080     * different behaviors if their normal behavior might interfere with the
18081     * host environment. For instance: the class spawns a thread in its
18082     * constructor, the drawing code relies on device-specific features, etc.
18083     *
18084     * This method is usually checked in the drawing code of custom widgets.
18085     *
18086     * @return True if this View is in edit mode, false otherwise.
18087     */
18088    public boolean isInEditMode() {
18089        return false;
18090    }
18091
18092    /**
18093     * If the View draws content inside its padding and enables fading edges,
18094     * it needs to support padding offsets. Padding offsets are added to the
18095     * fading edges to extend the length of the fade so that it covers pixels
18096     * drawn inside the padding.
18097     *
18098     * Subclasses of this class should override this method if they need
18099     * to draw content inside the padding.
18100     *
18101     * @return True if padding offset must be applied, false otherwise.
18102     *
18103     * @see #getLeftPaddingOffset()
18104     * @see #getRightPaddingOffset()
18105     * @see #getTopPaddingOffset()
18106     * @see #getBottomPaddingOffset()
18107     *
18108     * @since CURRENT
18109     */
18110    protected boolean isPaddingOffsetRequired() {
18111        return false;
18112    }
18113
18114    /**
18115     * Amount by which to extend the left fading region. Called only when
18116     * {@link #isPaddingOffsetRequired()} returns true.
18117     *
18118     * @return The left padding offset in pixels.
18119     *
18120     * @see #isPaddingOffsetRequired()
18121     *
18122     * @since CURRENT
18123     */
18124    protected int getLeftPaddingOffset() {
18125        return 0;
18126    }
18127
18128    /**
18129     * Amount by which to extend the right fading region. Called only when
18130     * {@link #isPaddingOffsetRequired()} returns true.
18131     *
18132     * @return The right padding offset in pixels.
18133     *
18134     * @see #isPaddingOffsetRequired()
18135     *
18136     * @since CURRENT
18137     */
18138    protected int getRightPaddingOffset() {
18139        return 0;
18140    }
18141
18142    /**
18143     * Amount by which to extend the top fading region. Called only when
18144     * {@link #isPaddingOffsetRequired()} returns true.
18145     *
18146     * @return The top padding offset in pixels.
18147     *
18148     * @see #isPaddingOffsetRequired()
18149     *
18150     * @since CURRENT
18151     */
18152    protected int getTopPaddingOffset() {
18153        return 0;
18154    }
18155
18156    /**
18157     * Amount by which to extend the bottom fading region. Called only when
18158     * {@link #isPaddingOffsetRequired()} returns true.
18159     *
18160     * @return The bottom padding offset in pixels.
18161     *
18162     * @see #isPaddingOffsetRequired()
18163     *
18164     * @since CURRENT
18165     */
18166    protected int getBottomPaddingOffset() {
18167        return 0;
18168    }
18169
18170    /**
18171     * @hide
18172     * @param offsetRequired
18173     */
18174    protected int getFadeTop(boolean offsetRequired) {
18175        int top = mPaddingTop;
18176        if (offsetRequired) top += getTopPaddingOffset();
18177        return top;
18178    }
18179
18180    /**
18181     * @hide
18182     * @param offsetRequired
18183     */
18184    protected int getFadeHeight(boolean offsetRequired) {
18185        int padding = mPaddingTop;
18186        if (offsetRequired) padding += getTopPaddingOffset();
18187        return mBottom - mTop - mPaddingBottom - padding;
18188    }
18189
18190    /**
18191     * <p>Indicates whether this view is attached to a hardware accelerated
18192     * window or not.</p>
18193     *
18194     * <p>Even if this method returns true, it does not mean that every call
18195     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18196     * accelerated {@link android.graphics.Canvas}. For instance, if this view
18197     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18198     * window is hardware accelerated,
18199     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18200     * return false, and this method will return true.</p>
18201     *
18202     * @return True if the view is attached to a window and the window is
18203     *         hardware accelerated; false in any other case.
18204     */
18205    @ViewDebug.ExportedProperty(category = "drawing")
18206    public boolean isHardwareAccelerated() {
18207        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18208    }
18209
18210    /**
18211     * Sets a rectangular area on this view to which the view will be clipped
18212     * when it is drawn. Setting the value to null will remove the clip bounds
18213     * and the view will draw normally, using its full bounds.
18214     *
18215     * @param clipBounds The rectangular area, in the local coordinates of
18216     * this view, to which future drawing operations will be clipped.
18217     */
18218    public void setClipBounds(Rect clipBounds) {
18219        if (clipBounds == mClipBounds
18220                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18221            return;
18222        }
18223        if (clipBounds != null) {
18224            if (mClipBounds == null) {
18225                mClipBounds = new Rect(clipBounds);
18226            } else {
18227                mClipBounds.set(clipBounds);
18228            }
18229        } else {
18230            mClipBounds = null;
18231        }
18232        mRenderNode.setClipBounds(mClipBounds);
18233        invalidateViewProperty(false, false);
18234    }
18235
18236    /**
18237     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18238     *
18239     * @return A copy of the current clip bounds if clip bounds are set,
18240     * otherwise null.
18241     */
18242    public Rect getClipBounds() {
18243        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18244    }
18245
18246
18247    /**
18248     * Populates an output rectangle with the clip bounds of the view,
18249     * returning {@code true} if successful or {@code false} if the view's
18250     * clip bounds are {@code null}.
18251     *
18252     * @param outRect rectangle in which to place the clip bounds of the view
18253     * @return {@code true} if successful or {@code false} if the view's
18254     *         clip bounds are {@code null}
18255     */
18256    public boolean getClipBounds(Rect outRect) {
18257        if (mClipBounds != null) {
18258            outRect.set(mClipBounds);
18259            return true;
18260        }
18261        return false;
18262    }
18263
18264    /**
18265     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18266     * case of an active Animation being run on the view.
18267     */
18268    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18269            Animation a, boolean scalingRequired) {
18270        Transformation invalidationTransform;
18271        final int flags = parent.mGroupFlags;
18272        final boolean initialized = a.isInitialized();
18273        if (!initialized) {
18274            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18275            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18276            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18277            onAnimationStart();
18278        }
18279
18280        final Transformation t = parent.getChildTransformation();
18281        boolean more = a.getTransformation(drawingTime, t, 1f);
18282        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18283            if (parent.mInvalidationTransformation == null) {
18284                parent.mInvalidationTransformation = new Transformation();
18285            }
18286            invalidationTransform = parent.mInvalidationTransformation;
18287            a.getTransformation(drawingTime, invalidationTransform, 1f);
18288        } else {
18289            invalidationTransform = t;
18290        }
18291
18292        if (more) {
18293            if (!a.willChangeBounds()) {
18294                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18295                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18296                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18297                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18298                    // The child need to draw an animation, potentially offscreen, so
18299                    // make sure we do not cancel invalidate requests
18300                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18301                    parent.invalidate(mLeft, mTop, mRight, mBottom);
18302                }
18303            } else {
18304                if (parent.mInvalidateRegion == null) {
18305                    parent.mInvalidateRegion = new RectF();
18306                }
18307                final RectF region = parent.mInvalidateRegion;
18308                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18309                        invalidationTransform);
18310
18311                // The child need to draw an animation, potentially offscreen, so
18312                // make sure we do not cancel invalidate requests
18313                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18314
18315                final int left = mLeft + (int) region.left;
18316                final int top = mTop + (int) region.top;
18317                parent.invalidate(left, top, left + (int) (region.width() + .5f),
18318                        top + (int) (region.height() + .5f));
18319            }
18320        }
18321        return more;
18322    }
18323
18324    /**
18325     * This method is called by getDisplayList() when a display list is recorded for a View.
18326     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18327     */
18328    void setDisplayListProperties(RenderNode renderNode) {
18329        if (renderNode != null) {
18330            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18331            renderNode.setClipToBounds(mParent instanceof ViewGroup
18332                    && ((ViewGroup) mParent).getClipChildren());
18333
18334            float alpha = 1;
18335            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18336                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18337                ViewGroup parentVG = (ViewGroup) mParent;
18338                final Transformation t = parentVG.getChildTransformation();
18339                if (parentVG.getChildStaticTransformation(this, t)) {
18340                    final int transformType = t.getTransformationType();
18341                    if (transformType != Transformation.TYPE_IDENTITY) {
18342                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18343                            alpha = t.getAlpha();
18344                        }
18345                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18346                            renderNode.setStaticMatrix(t.getMatrix());
18347                        }
18348                    }
18349                }
18350            }
18351            if (mTransformationInfo != null) {
18352                alpha *= getFinalAlpha();
18353                if (alpha < 1) {
18354                    final int multipliedAlpha = (int) (255 * alpha);
18355                    if (onSetAlpha(multipliedAlpha)) {
18356                        alpha = 1;
18357                    }
18358                }
18359                renderNode.setAlpha(alpha);
18360            } else if (alpha < 1) {
18361                renderNode.setAlpha(alpha);
18362            }
18363        }
18364    }
18365
18366    /**
18367     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18368     *
18369     * This is where the View specializes rendering behavior based on layer type,
18370     * and hardware acceleration.
18371     */
18372    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18373        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18374        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18375         *
18376         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18377         * HW accelerated, it can't handle drawing RenderNodes.
18378         */
18379        boolean drawingWithRenderNode = mAttachInfo != null
18380                && mAttachInfo.mHardwareAccelerated
18381                && hardwareAcceleratedCanvas;
18382
18383        boolean more = false;
18384        final boolean childHasIdentityMatrix = hasIdentityMatrix();
18385        final int parentFlags = parent.mGroupFlags;
18386
18387        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18388            parent.getChildTransformation().clear();
18389            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18390        }
18391
18392        Transformation transformToApply = null;
18393        boolean concatMatrix = false;
18394        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18395        final Animation a = getAnimation();
18396        if (a != null) {
18397            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18398            concatMatrix = a.willChangeTransformationMatrix();
18399            if (concatMatrix) {
18400                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18401            }
18402            transformToApply = parent.getChildTransformation();
18403        } else {
18404            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18405                // No longer animating: clear out old animation matrix
18406                mRenderNode.setAnimationMatrix(null);
18407                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18408            }
18409            if (!drawingWithRenderNode
18410                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18411                final Transformation t = parent.getChildTransformation();
18412                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18413                if (hasTransform) {
18414                    final int transformType = t.getTransformationType();
18415                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18416                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18417                }
18418            }
18419        }
18420
18421        concatMatrix |= !childHasIdentityMatrix;
18422
18423        // Sets the flag as early as possible to allow draw() implementations
18424        // to call invalidate() successfully when doing animations
18425        mPrivateFlags |= PFLAG_DRAWN;
18426
18427        if (!concatMatrix &&
18428                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18429                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18430                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18431                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18432            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18433            return more;
18434        }
18435        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18436
18437        if (hardwareAcceleratedCanvas) {
18438            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18439            // retain the flag's value temporarily in the mRecreateDisplayList flag
18440            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18441            mPrivateFlags &= ~PFLAG_INVALIDATED;
18442        }
18443
18444        RenderNode renderNode = null;
18445        Bitmap cache = null;
18446        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18447        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18448             if (layerType != LAYER_TYPE_NONE) {
18449                 // If not drawing with RenderNode, treat HW layers as SW
18450                 layerType = LAYER_TYPE_SOFTWARE;
18451                 buildDrawingCache(true);
18452            }
18453            cache = getDrawingCache(true);
18454        }
18455
18456        if (drawingWithRenderNode) {
18457            // Delay getting the display list until animation-driven alpha values are
18458            // set up and possibly passed on to the view
18459            renderNode = updateDisplayListIfDirty();
18460            if (!renderNode.isValid()) {
18461                // Uncommon, but possible. If a view is removed from the hierarchy during the call
18462                // to getDisplayList(), the display list will be marked invalid and we should not
18463                // try to use it again.
18464                renderNode = null;
18465                drawingWithRenderNode = false;
18466            }
18467        }
18468
18469        int sx = 0;
18470        int sy = 0;
18471        if (!drawingWithRenderNode) {
18472            computeScroll();
18473            sx = mScrollX;
18474            sy = mScrollY;
18475        }
18476
18477        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18478        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18479
18480        int restoreTo = -1;
18481        if (!drawingWithRenderNode || transformToApply != null) {
18482            restoreTo = canvas.save();
18483        }
18484        if (offsetForScroll) {
18485            canvas.translate(mLeft - sx, mTop - sy);
18486        } else {
18487            if (!drawingWithRenderNode) {
18488                canvas.translate(mLeft, mTop);
18489            }
18490            if (scalingRequired) {
18491                if (drawingWithRenderNode) {
18492                    // TODO: Might not need this if we put everything inside the DL
18493                    restoreTo = canvas.save();
18494                }
18495                // mAttachInfo cannot be null, otherwise scalingRequired == false
18496                final float scale = 1.0f / mAttachInfo.mApplicationScale;
18497                canvas.scale(scale, scale);
18498            }
18499        }
18500
18501        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18502        if (transformToApply != null
18503                || alpha < 1
18504                || !hasIdentityMatrix()
18505                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18506            if (transformToApply != null || !childHasIdentityMatrix) {
18507                int transX = 0;
18508                int transY = 0;
18509
18510                if (offsetForScroll) {
18511                    transX = -sx;
18512                    transY = -sy;
18513                }
18514
18515                if (transformToApply != null) {
18516                    if (concatMatrix) {
18517                        if (drawingWithRenderNode) {
18518                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
18519                        } else {
18520                            // Undo the scroll translation, apply the transformation matrix,
18521                            // then redo the scroll translate to get the correct result.
18522                            canvas.translate(-transX, -transY);
18523                            canvas.concat(transformToApply.getMatrix());
18524                            canvas.translate(transX, transY);
18525                        }
18526                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18527                    }
18528
18529                    float transformAlpha = transformToApply.getAlpha();
18530                    if (transformAlpha < 1) {
18531                        alpha *= transformAlpha;
18532                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18533                    }
18534                }
18535
18536                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18537                    canvas.translate(-transX, -transY);
18538                    canvas.concat(getMatrix());
18539                    canvas.translate(transX, transY);
18540                }
18541            }
18542
18543            // Deal with alpha if it is or used to be <1
18544            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18545                if (alpha < 1) {
18546                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18547                } else {
18548                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18549                }
18550                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18551                if (!drawingWithDrawingCache) {
18552                    final int multipliedAlpha = (int) (255 * alpha);
18553                    if (!onSetAlpha(multipliedAlpha)) {
18554                        if (drawingWithRenderNode) {
18555                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
18556                        } else if (layerType == LAYER_TYPE_NONE) {
18557                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
18558                                    multipliedAlpha);
18559                        }
18560                    } else {
18561                        // Alpha is handled by the child directly, clobber the layer's alpha
18562                        mPrivateFlags |= PFLAG_ALPHA_SET;
18563                    }
18564                }
18565            }
18566        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18567            onSetAlpha(255);
18568            mPrivateFlags &= ~PFLAG_ALPHA_SET;
18569        }
18570
18571        if (!drawingWithRenderNode) {
18572            // apply clips directly, since RenderNode won't do it for this draw
18573            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
18574                if (offsetForScroll) {
18575                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
18576                } else {
18577                    if (!scalingRequired || cache == null) {
18578                        canvas.clipRect(0, 0, getWidth(), getHeight());
18579                    } else {
18580                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
18581                    }
18582                }
18583            }
18584
18585            if (mClipBounds != null) {
18586                // clip bounds ignore scroll
18587                canvas.clipRect(mClipBounds);
18588            }
18589        }
18590
18591        if (!drawingWithDrawingCache) {
18592            if (drawingWithRenderNode) {
18593                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18594                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18595            } else {
18596                // Fast path for layouts with no backgrounds
18597                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18598                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18599                    dispatchDraw(canvas);
18600                } else {
18601                    draw(canvas);
18602                }
18603            }
18604        } else if (cache != null) {
18605            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18606            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
18607                // no layer paint, use temporary paint to draw bitmap
18608                Paint cachePaint = parent.mCachePaint;
18609                if (cachePaint == null) {
18610                    cachePaint = new Paint();
18611                    cachePaint.setDither(false);
18612                    parent.mCachePaint = cachePaint;
18613                }
18614                cachePaint.setAlpha((int) (alpha * 255));
18615                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
18616            } else {
18617                // use layer paint to draw the bitmap, merging the two alphas, but also restore
18618                int layerPaintAlpha = mLayerPaint.getAlpha();
18619                if (alpha < 1) {
18620                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
18621                }
18622                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
18623                if (alpha < 1) {
18624                    mLayerPaint.setAlpha(layerPaintAlpha);
18625                }
18626            }
18627        }
18628
18629        if (restoreTo >= 0) {
18630            canvas.restoreToCount(restoreTo);
18631        }
18632
18633        if (a != null && !more) {
18634            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
18635                onSetAlpha(255);
18636            }
18637            parent.finishAnimatingView(this, a);
18638        }
18639
18640        if (more && hardwareAcceleratedCanvas) {
18641            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18642                // alpha animations should cause the child to recreate its display list
18643                invalidate(true);
18644            }
18645        }
18646
18647        mRecreateDisplayList = false;
18648
18649        return more;
18650    }
18651
18652    static Paint getDebugPaint() {
18653        if (sDebugPaint == null) {
18654            sDebugPaint = new Paint();
18655            sDebugPaint.setAntiAlias(false);
18656        }
18657        return sDebugPaint;
18658    }
18659
18660    final int dipsToPixels(int dips) {
18661        float scale = getContext().getResources().getDisplayMetrics().density;
18662        return (int) (dips * scale + 0.5f);
18663    }
18664
18665    final private void debugDrawFocus(Canvas canvas) {
18666        if (isFocused()) {
18667            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
18668            final int l = mScrollX;
18669            final int r = l + mRight - mLeft;
18670            final int t = mScrollY;
18671            final int b = t + mBottom - mTop;
18672
18673            final Paint paint = getDebugPaint();
18674            paint.setColor(DEBUG_CORNERS_COLOR);
18675
18676            // Draw squares in corners.
18677            paint.setStyle(Paint.Style.FILL);
18678            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
18679            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
18680            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
18681            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
18682
18683            // Draw big X across the view.
18684            paint.setStyle(Paint.Style.STROKE);
18685            canvas.drawLine(l, t, r, b, paint);
18686            canvas.drawLine(l, b, r, t, paint);
18687        }
18688    }
18689
18690    /**
18691     * Manually render this view (and all of its children) to the given Canvas.
18692     * The view must have already done a full layout before this function is
18693     * called.  When implementing a view, implement
18694     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
18695     * If you do need to override this method, call the superclass version.
18696     *
18697     * @param canvas The Canvas to which the View is rendered.
18698     */
18699    @CallSuper
18700    public void draw(Canvas canvas) {
18701        final int privateFlags = mPrivateFlags;
18702        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
18703                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
18704        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
18705
18706        /*
18707         * Draw traversal performs several drawing steps which must be executed
18708         * in the appropriate order:
18709         *
18710         *      1. Draw the background
18711         *      2. If necessary, save the canvas' layers to prepare for fading
18712         *      3. Draw view's content
18713         *      4. Draw children
18714         *      5. If necessary, draw the fading edges and restore layers
18715         *      6. Draw decorations (scrollbars for instance)
18716         */
18717
18718        // Step 1, draw the background, if needed
18719        int saveCount;
18720
18721        if (!dirtyOpaque) {
18722            drawBackground(canvas);
18723        }
18724
18725        // skip step 2 & 5 if possible (common case)
18726        final int viewFlags = mViewFlags;
18727        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
18728        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
18729        if (!verticalEdges && !horizontalEdges) {
18730            // Step 3, draw the content
18731            if (!dirtyOpaque) onDraw(canvas);
18732
18733            // Step 4, draw the children
18734            dispatchDraw(canvas);
18735
18736            drawAutofilledHighlight(canvas);
18737
18738            // Overlay is part of the content and draws beneath Foreground
18739            if (mOverlay != null && !mOverlay.isEmpty()) {
18740                mOverlay.getOverlayView().dispatchDraw(canvas);
18741            }
18742
18743            // Step 6, draw decorations (foreground, scrollbars)
18744            onDrawForeground(canvas);
18745
18746            // Step 7, draw the default focus highlight
18747            drawDefaultFocusHighlight(canvas);
18748
18749            if (debugDraw()) {
18750                debugDrawFocus(canvas);
18751            }
18752
18753            // we're done...
18754            return;
18755        }
18756
18757        /*
18758         * Here we do the full fledged routine...
18759         * (this is an uncommon case where speed matters less,
18760         * this is why we repeat some of the tests that have been
18761         * done above)
18762         */
18763
18764        boolean drawTop = false;
18765        boolean drawBottom = false;
18766        boolean drawLeft = false;
18767        boolean drawRight = false;
18768
18769        float topFadeStrength = 0.0f;
18770        float bottomFadeStrength = 0.0f;
18771        float leftFadeStrength = 0.0f;
18772        float rightFadeStrength = 0.0f;
18773
18774        // Step 2, save the canvas' layers
18775        int paddingLeft = mPaddingLeft;
18776
18777        final boolean offsetRequired = isPaddingOffsetRequired();
18778        if (offsetRequired) {
18779            paddingLeft += getLeftPaddingOffset();
18780        }
18781
18782        int left = mScrollX + paddingLeft;
18783        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
18784        int top = mScrollY + getFadeTop(offsetRequired);
18785        int bottom = top + getFadeHeight(offsetRequired);
18786
18787        if (offsetRequired) {
18788            right += getRightPaddingOffset();
18789            bottom += getBottomPaddingOffset();
18790        }
18791
18792        final ScrollabilityCache scrollabilityCache = mScrollCache;
18793        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
18794        int length = (int) fadeHeight;
18795
18796        // clip the fade length if top and bottom fades overlap
18797        // overlapping fades produce odd-looking artifacts
18798        if (verticalEdges && (top + length > bottom - length)) {
18799            length = (bottom - top) / 2;
18800        }
18801
18802        // also clip horizontal fades if necessary
18803        if (horizontalEdges && (left + length > right - length)) {
18804            length = (right - left) / 2;
18805        }
18806
18807        if (verticalEdges) {
18808            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
18809            drawTop = topFadeStrength * fadeHeight > 1.0f;
18810            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
18811            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
18812        }
18813
18814        if (horizontalEdges) {
18815            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
18816            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
18817            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
18818            drawRight = rightFadeStrength * fadeHeight > 1.0f;
18819        }
18820
18821        saveCount = canvas.getSaveCount();
18822
18823        int solidColor = getSolidColor();
18824        if (solidColor == 0) {
18825            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
18826
18827            if (drawTop) {
18828                canvas.saveLayer(left, top, right, top + length, null, flags);
18829            }
18830
18831            if (drawBottom) {
18832                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
18833            }
18834
18835            if (drawLeft) {
18836                canvas.saveLayer(left, top, left + length, bottom, null, flags);
18837            }
18838
18839            if (drawRight) {
18840                canvas.saveLayer(right - length, top, right, bottom, null, flags);
18841            }
18842        } else {
18843            scrollabilityCache.setFadeColor(solidColor);
18844        }
18845
18846        // Step 3, draw the content
18847        if (!dirtyOpaque) onDraw(canvas);
18848
18849        // Step 4, draw the children
18850        dispatchDraw(canvas);
18851
18852        // Step 5, draw the fade effect and restore layers
18853        final Paint p = scrollabilityCache.paint;
18854        final Matrix matrix = scrollabilityCache.matrix;
18855        final Shader fade = scrollabilityCache.shader;
18856
18857        if (drawTop) {
18858            matrix.setScale(1, fadeHeight * topFadeStrength);
18859            matrix.postTranslate(left, top);
18860            fade.setLocalMatrix(matrix);
18861            p.setShader(fade);
18862            canvas.drawRect(left, top, right, top + length, p);
18863        }
18864
18865        if (drawBottom) {
18866            matrix.setScale(1, fadeHeight * bottomFadeStrength);
18867            matrix.postRotate(180);
18868            matrix.postTranslate(left, bottom);
18869            fade.setLocalMatrix(matrix);
18870            p.setShader(fade);
18871            canvas.drawRect(left, bottom - length, right, bottom, p);
18872        }
18873
18874        if (drawLeft) {
18875            matrix.setScale(1, fadeHeight * leftFadeStrength);
18876            matrix.postRotate(-90);
18877            matrix.postTranslate(left, top);
18878            fade.setLocalMatrix(matrix);
18879            p.setShader(fade);
18880            canvas.drawRect(left, top, left + length, bottom, p);
18881        }
18882
18883        if (drawRight) {
18884            matrix.setScale(1, fadeHeight * rightFadeStrength);
18885            matrix.postRotate(90);
18886            matrix.postTranslate(right, top);
18887            fade.setLocalMatrix(matrix);
18888            p.setShader(fade);
18889            canvas.drawRect(right - length, top, right, bottom, p);
18890        }
18891
18892        canvas.restoreToCount(saveCount);
18893
18894        drawAutofilledHighlight(canvas);
18895
18896        // Overlay is part of the content and draws beneath Foreground
18897        if (mOverlay != null && !mOverlay.isEmpty()) {
18898            mOverlay.getOverlayView().dispatchDraw(canvas);
18899        }
18900
18901        // Step 6, draw decorations (foreground, scrollbars)
18902        onDrawForeground(canvas);
18903
18904        if (debugDraw()) {
18905            debugDrawFocus(canvas);
18906        }
18907    }
18908
18909    /**
18910     * Draws the background onto the specified canvas.
18911     *
18912     * @param canvas Canvas on which to draw the background
18913     */
18914    private void drawBackground(Canvas canvas) {
18915        final Drawable background = mBackground;
18916        if (background == null) {
18917            return;
18918        }
18919
18920        setBackgroundBounds();
18921
18922        // Attempt to use a display list if requested.
18923        if (canvas.isHardwareAccelerated() && mAttachInfo != null
18924                && mAttachInfo.mThreadedRenderer != null) {
18925            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
18926
18927            final RenderNode renderNode = mBackgroundRenderNode;
18928            if (renderNode != null && renderNode.isValid()) {
18929                setBackgroundRenderNodeProperties(renderNode);
18930                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18931                return;
18932            }
18933        }
18934
18935        final int scrollX = mScrollX;
18936        final int scrollY = mScrollY;
18937        if ((scrollX | scrollY) == 0) {
18938            background.draw(canvas);
18939        } else {
18940            canvas.translate(scrollX, scrollY);
18941            background.draw(canvas);
18942            canvas.translate(-scrollX, -scrollY);
18943        }
18944    }
18945
18946    /**
18947     * Sets the correct background bounds and rebuilds the outline, if needed.
18948     * <p/>
18949     * This is called by LayoutLib.
18950     */
18951    void setBackgroundBounds() {
18952        if (mBackgroundSizeChanged && mBackground != null) {
18953            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
18954            mBackgroundSizeChanged = false;
18955            rebuildOutline();
18956        }
18957    }
18958
18959    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
18960        renderNode.setTranslationX(mScrollX);
18961        renderNode.setTranslationY(mScrollY);
18962    }
18963
18964    /**
18965     * Creates a new display list or updates the existing display list for the
18966     * specified Drawable.
18967     *
18968     * @param drawable Drawable for which to create a display list
18969     * @param renderNode Existing RenderNode, or {@code null}
18970     * @return A valid display list for the specified drawable
18971     */
18972    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
18973        if (renderNode == null) {
18974            renderNode = RenderNode.create(drawable.getClass().getName(), this);
18975        }
18976
18977        final Rect bounds = drawable.getBounds();
18978        final int width = bounds.width();
18979        final int height = bounds.height();
18980        final DisplayListCanvas canvas = renderNode.start(width, height);
18981
18982        // Reverse left/top translation done by drawable canvas, which will
18983        // instead be applied by rendernode's LTRB bounds below. This way, the
18984        // drawable's bounds match with its rendernode bounds and its content
18985        // will lie within those bounds in the rendernode tree.
18986        canvas.translate(-bounds.left, -bounds.top);
18987
18988        try {
18989            drawable.draw(canvas);
18990        } finally {
18991            renderNode.end(canvas);
18992        }
18993
18994        // Set up drawable properties that are view-independent.
18995        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
18996        renderNode.setProjectBackwards(drawable.isProjected());
18997        renderNode.setProjectionReceiver(true);
18998        renderNode.setClipToBounds(false);
18999        return renderNode;
19000    }
19001
19002    /**
19003     * Returns the overlay for this view, creating it if it does not yet exist.
19004     * Adding drawables to the overlay will cause them to be displayed whenever
19005     * the view itself is redrawn. Objects in the overlay should be actively
19006     * managed: remove them when they should not be displayed anymore. The
19007     * overlay will always have the same size as its host view.
19008     *
19009     * <p>Note: Overlays do not currently work correctly with {@link
19010     * SurfaceView} or {@link TextureView}; contents in overlays for these
19011     * types of views may not display correctly.</p>
19012     *
19013     * @return The ViewOverlay object for this view.
19014     * @see ViewOverlay
19015     */
19016    public ViewOverlay getOverlay() {
19017        if (mOverlay == null) {
19018            mOverlay = new ViewOverlay(mContext, this);
19019        }
19020        return mOverlay;
19021    }
19022
19023    /**
19024     * Override this if your view is known to always be drawn on top of a solid color background,
19025     * and needs to draw fading edges. Returning a non-zero color enables the view system to
19026     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
19027     * should be set to 0xFF.
19028     *
19029     * @see #setVerticalFadingEdgeEnabled(boolean)
19030     * @see #setHorizontalFadingEdgeEnabled(boolean)
19031     *
19032     * @return The known solid color background for this view, or 0 if the color may vary
19033     */
19034    @ViewDebug.ExportedProperty(category = "drawing")
19035    @ColorInt
19036    public int getSolidColor() {
19037        return 0;
19038    }
19039
19040    /**
19041     * Build a human readable string representation of the specified view flags.
19042     *
19043     * @param flags the view flags to convert to a string
19044     * @return a String representing the supplied flags
19045     */
19046    private static String printFlags(int flags) {
19047        String output = "";
19048        int numFlags = 0;
19049        if ((flags & FOCUSABLE) == FOCUSABLE) {
19050            output += "TAKES_FOCUS";
19051            numFlags++;
19052        }
19053
19054        switch (flags & VISIBILITY_MASK) {
19055        case INVISIBLE:
19056            if (numFlags > 0) {
19057                output += " ";
19058            }
19059            output += "INVISIBLE";
19060            // USELESS HERE numFlags++;
19061            break;
19062        case GONE:
19063            if (numFlags > 0) {
19064                output += " ";
19065            }
19066            output += "GONE";
19067            // USELESS HERE numFlags++;
19068            break;
19069        default:
19070            break;
19071        }
19072        return output;
19073    }
19074
19075    /**
19076     * Build a human readable string representation of the specified private
19077     * view flags.
19078     *
19079     * @param privateFlags the private view flags to convert to a string
19080     * @return a String representing the supplied flags
19081     */
19082    private static String printPrivateFlags(int privateFlags) {
19083        String output = "";
19084        int numFlags = 0;
19085
19086        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
19087            output += "WANTS_FOCUS";
19088            numFlags++;
19089        }
19090
19091        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
19092            if (numFlags > 0) {
19093                output += " ";
19094            }
19095            output += "FOCUSED";
19096            numFlags++;
19097        }
19098
19099        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
19100            if (numFlags > 0) {
19101                output += " ";
19102            }
19103            output += "SELECTED";
19104            numFlags++;
19105        }
19106
19107        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
19108            if (numFlags > 0) {
19109                output += " ";
19110            }
19111            output += "IS_ROOT_NAMESPACE";
19112            numFlags++;
19113        }
19114
19115        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
19116            if (numFlags > 0) {
19117                output += " ";
19118            }
19119            output += "HAS_BOUNDS";
19120            numFlags++;
19121        }
19122
19123        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
19124            if (numFlags > 0) {
19125                output += " ";
19126            }
19127            output += "DRAWN";
19128            // USELESS HERE numFlags++;
19129        }
19130        return output;
19131    }
19132
19133    /**
19134     * <p>Indicates whether or not this view's layout will be requested during
19135     * the next hierarchy layout pass.</p>
19136     *
19137     * @return true if the layout will be forced during next layout pass
19138     */
19139    public boolean isLayoutRequested() {
19140        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19141    }
19142
19143    /**
19144     * Return true if o is a ViewGroup that is laying out using optical bounds.
19145     * @hide
19146     */
19147    public static boolean isLayoutModeOptical(Object o) {
19148        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19149    }
19150
19151    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19152        Insets parentInsets = mParent instanceof View ?
19153                ((View) mParent).getOpticalInsets() : Insets.NONE;
19154        Insets childInsets = getOpticalInsets();
19155        return setFrame(
19156                left   + parentInsets.left - childInsets.left,
19157                top    + parentInsets.top  - childInsets.top,
19158                right  + parentInsets.left + childInsets.right,
19159                bottom + parentInsets.top  + childInsets.bottom);
19160    }
19161
19162    /**
19163     * Assign a size and position to a view and all of its
19164     * descendants
19165     *
19166     * <p>This is the second phase of the layout mechanism.
19167     * (The first is measuring). In this phase, each parent calls
19168     * layout on all of its children to position them.
19169     * This is typically done using the child measurements
19170     * that were stored in the measure pass().</p>
19171     *
19172     * <p>Derived classes should not override this method.
19173     * Derived classes with children should override
19174     * onLayout. In that method, they should
19175     * call layout on each of their children.</p>
19176     *
19177     * @param l Left position, relative to parent
19178     * @param t Top position, relative to parent
19179     * @param r Right position, relative to parent
19180     * @param b Bottom position, relative to parent
19181     */
19182    @SuppressWarnings({"unchecked"})
19183    public void layout(int l, int t, int r, int b) {
19184        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19185            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19186            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19187        }
19188
19189        int oldL = mLeft;
19190        int oldT = mTop;
19191        int oldB = mBottom;
19192        int oldR = mRight;
19193
19194        boolean changed = isLayoutModeOptical(mParent) ?
19195                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19196
19197        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19198            onLayout(changed, l, t, r, b);
19199
19200            if (shouldDrawRoundScrollbar()) {
19201                if(mRoundScrollbarRenderer == null) {
19202                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19203                }
19204            } else {
19205                mRoundScrollbarRenderer = null;
19206            }
19207
19208            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19209
19210            ListenerInfo li = mListenerInfo;
19211            if (li != null && li.mOnLayoutChangeListeners != null) {
19212                ArrayList<OnLayoutChangeListener> listenersCopy =
19213                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19214                int numListeners = listenersCopy.size();
19215                for (int i = 0; i < numListeners; ++i) {
19216                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19217                }
19218            }
19219        }
19220
19221        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19222        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19223    }
19224
19225    /**
19226     * Called from layout when this view should
19227     * assign a size and position to each of its children.
19228     *
19229     * Derived classes with children should override
19230     * this method and call layout on each of
19231     * their children.
19232     * @param changed This is a new size or position for this view
19233     * @param left Left position, relative to parent
19234     * @param top Top position, relative to parent
19235     * @param right Right position, relative to parent
19236     * @param bottom Bottom position, relative to parent
19237     */
19238    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19239    }
19240
19241    /**
19242     * Assign a size and position to this view.
19243     *
19244     * This is called from layout.
19245     *
19246     * @param left Left position, relative to parent
19247     * @param top Top position, relative to parent
19248     * @param right Right position, relative to parent
19249     * @param bottom Bottom position, relative to parent
19250     * @return true if the new size and position are different than the
19251     *         previous ones
19252     * {@hide}
19253     */
19254    protected boolean setFrame(int left, int top, int right, int bottom) {
19255        boolean changed = false;
19256
19257        if (DBG) {
19258            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19259                    + right + "," + bottom + ")");
19260        }
19261
19262        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19263            changed = true;
19264
19265            // Remember our drawn bit
19266            int drawn = mPrivateFlags & PFLAG_DRAWN;
19267
19268            int oldWidth = mRight - mLeft;
19269            int oldHeight = mBottom - mTop;
19270            int newWidth = right - left;
19271            int newHeight = bottom - top;
19272            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19273
19274            // Invalidate our old position
19275            invalidate(sizeChanged);
19276
19277            mLeft = left;
19278            mTop = top;
19279            mRight = right;
19280            mBottom = bottom;
19281            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19282
19283            mPrivateFlags |= PFLAG_HAS_BOUNDS;
19284
19285
19286            if (sizeChanged) {
19287                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19288            }
19289
19290            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19291                // If we are visible, force the DRAWN bit to on so that
19292                // this invalidate will go through (at least to our parent).
19293                // This is because someone may have invalidated this view
19294                // before this call to setFrame came in, thereby clearing
19295                // the DRAWN bit.
19296                mPrivateFlags |= PFLAG_DRAWN;
19297                invalidate(sizeChanged);
19298                // parent display list may need to be recreated based on a change in the bounds
19299                // of any child
19300                invalidateParentCaches();
19301            }
19302
19303            // Reset drawn bit to original value (invalidate turns it off)
19304            mPrivateFlags |= drawn;
19305
19306            mBackgroundSizeChanged = true;
19307            mDefaultFocusHighlightSizeChanged = true;
19308            if (mForegroundInfo != null) {
19309                mForegroundInfo.mBoundsChanged = true;
19310            }
19311
19312            notifySubtreeAccessibilityStateChangedIfNeeded();
19313        }
19314        return changed;
19315    }
19316
19317    /**
19318     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19319     * @hide
19320     */
19321    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19322        setFrame(left, top, right, bottom);
19323    }
19324
19325    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19326        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19327        if (mOverlay != null) {
19328            mOverlay.getOverlayView().setRight(newWidth);
19329            mOverlay.getOverlayView().setBottom(newHeight);
19330        }
19331        rebuildOutline();
19332    }
19333
19334    /**
19335     * Finalize inflating a view from XML.  This is called as the last phase
19336     * of inflation, after all child views have been added.
19337     *
19338     * <p>Even if the subclass overrides onFinishInflate, they should always be
19339     * sure to call the super method, so that we get called.
19340     */
19341    @CallSuper
19342    protected void onFinishInflate() {
19343    }
19344
19345    /**
19346     * Returns the resources associated with this view.
19347     *
19348     * @return Resources object.
19349     */
19350    public Resources getResources() {
19351        return mResources;
19352    }
19353
19354    /**
19355     * Invalidates the specified Drawable.
19356     *
19357     * @param drawable the drawable to invalidate
19358     */
19359    @Override
19360    public void invalidateDrawable(@NonNull Drawable drawable) {
19361        if (verifyDrawable(drawable)) {
19362            final Rect dirty = drawable.getDirtyBounds();
19363            final int scrollX = mScrollX;
19364            final int scrollY = mScrollY;
19365
19366            invalidate(dirty.left + scrollX, dirty.top + scrollY,
19367                    dirty.right + scrollX, dirty.bottom + scrollY);
19368            rebuildOutline();
19369        }
19370    }
19371
19372    /**
19373     * Schedules an action on a drawable to occur at a specified time.
19374     *
19375     * @param who the recipient of the action
19376     * @param what the action to run on the drawable
19377     * @param when the time at which the action must occur. Uses the
19378     *        {@link SystemClock#uptimeMillis} timebase.
19379     */
19380    @Override
19381    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19382        if (verifyDrawable(who) && what != null) {
19383            final long delay = when - SystemClock.uptimeMillis();
19384            if (mAttachInfo != null) {
19385                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19386                        Choreographer.CALLBACK_ANIMATION, what, who,
19387                        Choreographer.subtractFrameDelay(delay));
19388            } else {
19389                // Postpone the runnable until we know
19390                // on which thread it needs to run.
19391                getRunQueue().postDelayed(what, delay);
19392            }
19393        }
19394    }
19395
19396    /**
19397     * Cancels a scheduled action on a drawable.
19398     *
19399     * @param who the recipient of the action
19400     * @param what the action to cancel
19401     */
19402    @Override
19403    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19404        if (verifyDrawable(who) && what != null) {
19405            if (mAttachInfo != null) {
19406                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19407                        Choreographer.CALLBACK_ANIMATION, what, who);
19408            }
19409            getRunQueue().removeCallbacks(what);
19410        }
19411    }
19412
19413    /**
19414     * Unschedule any events associated with the given Drawable.  This can be
19415     * used when selecting a new Drawable into a view, so that the previous
19416     * one is completely unscheduled.
19417     *
19418     * @param who The Drawable to unschedule.
19419     *
19420     * @see #drawableStateChanged
19421     */
19422    public void unscheduleDrawable(Drawable who) {
19423        if (mAttachInfo != null && who != null) {
19424            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19425                    Choreographer.CALLBACK_ANIMATION, null, who);
19426        }
19427    }
19428
19429    /**
19430     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19431     * that the View directionality can and will be resolved before its Drawables.
19432     *
19433     * Will call {@link View#onResolveDrawables} when resolution is done.
19434     *
19435     * @hide
19436     */
19437    protected void resolveDrawables() {
19438        // Drawables resolution may need to happen before resolving the layout direction (which is
19439        // done only during the measure() call).
19440        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19441        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19442        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19443        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19444        // direction to be resolved as its resolved value will be the same as its raw value.
19445        if (!isLayoutDirectionResolved() &&
19446                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19447            return;
19448        }
19449
19450        final int layoutDirection = isLayoutDirectionResolved() ?
19451                getLayoutDirection() : getRawLayoutDirection();
19452
19453        if (mBackground != null) {
19454            mBackground.setLayoutDirection(layoutDirection);
19455        }
19456        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19457            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19458        }
19459        if (mDefaultFocusHighlight != null) {
19460            mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
19461        }
19462        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19463        onResolveDrawables(layoutDirection);
19464    }
19465
19466    boolean areDrawablesResolved() {
19467        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19468    }
19469
19470    /**
19471     * Called when layout direction has been resolved.
19472     *
19473     * The default implementation does nothing.
19474     *
19475     * @param layoutDirection The resolved layout direction.
19476     *
19477     * @see #LAYOUT_DIRECTION_LTR
19478     * @see #LAYOUT_DIRECTION_RTL
19479     *
19480     * @hide
19481     */
19482    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19483    }
19484
19485    /**
19486     * @hide
19487     */
19488    protected void resetResolvedDrawables() {
19489        resetResolvedDrawablesInternal();
19490    }
19491
19492    void resetResolvedDrawablesInternal() {
19493        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19494    }
19495
19496    /**
19497     * If your view subclass is displaying its own Drawable objects, it should
19498     * override this function and return true for any Drawable it is
19499     * displaying.  This allows animations for those drawables to be
19500     * scheduled.
19501     *
19502     * <p>Be sure to call through to the super class when overriding this
19503     * function.
19504     *
19505     * @param who The Drawable to verify.  Return true if it is one you are
19506     *            displaying, else return the result of calling through to the
19507     *            super class.
19508     *
19509     * @return boolean If true than the Drawable is being displayed in the
19510     *         view; else false and it is not allowed to animate.
19511     *
19512     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19513     * @see #drawableStateChanged()
19514     */
19515    @CallSuper
19516    protected boolean verifyDrawable(@NonNull Drawable who) {
19517        // Avoid verifying the scroll bar drawable so that we don't end up in
19518        // an invalidation loop. This effectively prevents the scroll bar
19519        // drawable from triggering invalidations and scheduling runnables.
19520        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
19521                || (mDefaultFocusHighlight == who);
19522    }
19523
19524    /**
19525     * This function is called whenever the state of the view changes in such
19526     * a way that it impacts the state of drawables being shown.
19527     * <p>
19528     * If the View has a StateListAnimator, it will also be called to run necessary state
19529     * change animations.
19530     * <p>
19531     * Be sure to call through to the superclass when overriding this function.
19532     *
19533     * @see Drawable#setState(int[])
19534     */
19535    @CallSuper
19536    protected void drawableStateChanged() {
19537        final int[] state = getDrawableState();
19538        boolean changed = false;
19539
19540        final Drawable bg = mBackground;
19541        if (bg != null && bg.isStateful()) {
19542            changed |= bg.setState(state);
19543        }
19544
19545        final Drawable hl = mDefaultFocusHighlight;
19546        if (hl != null && hl.isStateful()) {
19547            changed |= hl.setState(state);
19548        }
19549
19550        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19551        if (fg != null && fg.isStateful()) {
19552            changed |= fg.setState(state);
19553        }
19554
19555        if (mScrollCache != null) {
19556            final Drawable scrollBar = mScrollCache.scrollBar;
19557            if (scrollBar != null && scrollBar.isStateful()) {
19558                changed |= scrollBar.setState(state)
19559                        && mScrollCache.state != ScrollabilityCache.OFF;
19560            }
19561        }
19562
19563        if (mStateListAnimator != null) {
19564            mStateListAnimator.setState(state);
19565        }
19566
19567        if (changed) {
19568            invalidate();
19569        }
19570    }
19571
19572    /**
19573     * This function is called whenever the view hotspot changes and needs to
19574     * be propagated to drawables or child views managed by the view.
19575     * <p>
19576     * Dispatching to child views is handled by
19577     * {@link #dispatchDrawableHotspotChanged(float, float)}.
19578     * <p>
19579     * Be sure to call through to the superclass when overriding this function.
19580     *
19581     * @param x hotspot x coordinate
19582     * @param y hotspot y coordinate
19583     */
19584    @CallSuper
19585    public void drawableHotspotChanged(float x, float y) {
19586        if (mBackground != null) {
19587            mBackground.setHotspot(x, y);
19588        }
19589        if (mDefaultFocusHighlight != null) {
19590            mDefaultFocusHighlight.setHotspot(x, y);
19591        }
19592        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19593            mForegroundInfo.mDrawable.setHotspot(x, y);
19594        }
19595
19596        dispatchDrawableHotspotChanged(x, y);
19597    }
19598
19599    /**
19600     * Dispatches drawableHotspotChanged to all of this View's children.
19601     *
19602     * @param x hotspot x coordinate
19603     * @param y hotspot y coordinate
19604     * @see #drawableHotspotChanged(float, float)
19605     */
19606    public void dispatchDrawableHotspotChanged(float x, float y) {
19607    }
19608
19609    /**
19610     * Call this to force a view to update its drawable state. This will cause
19611     * drawableStateChanged to be called on this view. Views that are interested
19612     * in the new state should call getDrawableState.
19613     *
19614     * @see #drawableStateChanged
19615     * @see #getDrawableState
19616     */
19617    public void refreshDrawableState() {
19618        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
19619        drawableStateChanged();
19620
19621        ViewParent parent = mParent;
19622        if (parent != null) {
19623            parent.childDrawableStateChanged(this);
19624        }
19625    }
19626
19627    /**
19628     * Create a default focus highlight if it doesn't exist.
19629     * @return a default focus highlight.
19630     */
19631    private Drawable getDefaultFocusHighlightDrawable() {
19632        if (mDefaultFocusHighlightCache == null) {
19633            if (mContext != null) {
19634                final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
19635                final TypedArray ta = mContext.obtainStyledAttributes(attrs);
19636                mDefaultFocusHighlightCache = ta.getDrawable(0);
19637                ta.recycle();
19638            }
19639        }
19640        return mDefaultFocusHighlightCache;
19641    }
19642
19643    /**
19644     * Set the current default focus highlight.
19645     * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
19646     */
19647    private void setDefaultFocusHighlight(Drawable highlight) {
19648        mDefaultFocusHighlight = highlight;
19649        mDefaultFocusHighlightSizeChanged = true;
19650        if (highlight != null) {
19651            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
19652                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
19653            }
19654            highlight.setLayoutDirection(getLayoutDirection());
19655            if (highlight.isStateful()) {
19656                highlight.setState(getDrawableState());
19657            }
19658            if (isAttachedToWindow()) {
19659                highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19660            }
19661            // Set callback last, since the view may still be initializing.
19662            highlight.setCallback(this);
19663        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
19664                && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
19665            mPrivateFlags |= PFLAG_SKIP_DRAW;
19666        }
19667        requestLayout();
19668        invalidate();
19669    }
19670
19671    /**
19672     * Check whether we need to draw a default focus highlight when this view gets focused,
19673     * which requires:
19674     * <ul>
19675     *     <li>In the background, {@link android.R.attr#state_focused} is not defined.</li>
19676     *     <li>This view is not in touch mode.</li>
19677     *     <li>This view doesn't opt out for a default focus highlight, via
19678     *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
19679     *     <li>This view is attached to window.</li>
19680     * </ul>
19681     * @return {@code true} if a default focus highlight is needed.
19682     */
19683    private boolean isDefaultFocusHighlightNeeded(Drawable background) {
19684        final boolean hasFocusStateSpecified = background == null || !background.isStateful()
19685                || !background.hasFocusStateSpecified();
19686        return !isInTouchMode() && getDefaultFocusHighlightEnabled() && hasFocusStateSpecified
19687                && isAttachedToWindow() && sUseDefaultFocusHighlight;
19688    }
19689
19690    /**
19691     * When this view is focused, switches on/off the default focused highlight.
19692     * <p>
19693     * This always happens when this view is focused, and only at this moment the default focus
19694     * highlight can be visible.
19695     */
19696    private void switchDefaultFocusHighlight() {
19697        if (isFocused()) {
19698            final boolean needed = isDefaultFocusHighlightNeeded(mBackground);
19699            final boolean active = mDefaultFocusHighlight != null;
19700            if (needed && !active) {
19701                setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
19702            } else if (!needed && active) {
19703                // The highlight is no longer needed, so tear it down.
19704                setDefaultFocusHighlight(null);
19705            }
19706        }
19707    }
19708
19709    /**
19710     * Draw the default focus highlight onto the canvas.
19711     * @param canvas the canvas where we're drawing the highlight.
19712     */
19713    private void drawDefaultFocusHighlight(Canvas canvas) {
19714        if (mDefaultFocusHighlight != null) {
19715            if (mDefaultFocusHighlightSizeChanged) {
19716                mDefaultFocusHighlightSizeChanged = false;
19717                final int l = mScrollX;
19718                final int r = l + mRight - mLeft;
19719                final int t = mScrollY;
19720                final int b = t + mBottom - mTop;
19721                mDefaultFocusHighlight.setBounds(l, t, r, b);
19722            }
19723            mDefaultFocusHighlight.draw(canvas);
19724        }
19725    }
19726
19727    /**
19728     * Return an array of resource IDs of the drawable states representing the
19729     * current state of the view.
19730     *
19731     * @return The current drawable state
19732     *
19733     * @see Drawable#setState(int[])
19734     * @see #drawableStateChanged()
19735     * @see #onCreateDrawableState(int)
19736     */
19737    public final int[] getDrawableState() {
19738        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
19739            return mDrawableState;
19740        } else {
19741            mDrawableState = onCreateDrawableState(0);
19742            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
19743            return mDrawableState;
19744        }
19745    }
19746
19747    /**
19748     * Generate the new {@link android.graphics.drawable.Drawable} state for
19749     * this view. This is called by the view
19750     * system when the cached Drawable state is determined to be invalid.  To
19751     * retrieve the current state, you should use {@link #getDrawableState}.
19752     *
19753     * @param extraSpace if non-zero, this is the number of extra entries you
19754     * would like in the returned array in which you can place your own
19755     * states.
19756     *
19757     * @return Returns an array holding the current {@link Drawable} state of
19758     * the view.
19759     *
19760     * @see #mergeDrawableStates(int[], int[])
19761     */
19762    protected int[] onCreateDrawableState(int extraSpace) {
19763        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
19764                mParent instanceof View) {
19765            return ((View) mParent).onCreateDrawableState(extraSpace);
19766        }
19767
19768        int[] drawableState;
19769
19770        int privateFlags = mPrivateFlags;
19771
19772        int viewStateIndex = 0;
19773        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
19774        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
19775        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
19776        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
19777        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
19778        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
19779        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
19780                ThreadedRenderer.isAvailable()) {
19781            // This is set if HW acceleration is requested, even if the current
19782            // process doesn't allow it.  This is just to allow app preview
19783            // windows to better match their app.
19784            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
19785        }
19786        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
19787
19788        final int privateFlags2 = mPrivateFlags2;
19789        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
19790            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
19791        }
19792        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
19793            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
19794        }
19795
19796        drawableState = StateSet.get(viewStateIndex);
19797
19798        //noinspection ConstantIfStatement
19799        if (false) {
19800            Log.i("View", "drawableStateIndex=" + viewStateIndex);
19801            Log.i("View", toString()
19802                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
19803                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
19804                    + " fo=" + hasFocus()
19805                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
19806                    + " wf=" + hasWindowFocus()
19807                    + ": " + Arrays.toString(drawableState));
19808        }
19809
19810        if (extraSpace == 0) {
19811            return drawableState;
19812        }
19813
19814        final int[] fullState;
19815        if (drawableState != null) {
19816            fullState = new int[drawableState.length + extraSpace];
19817            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
19818        } else {
19819            fullState = new int[extraSpace];
19820        }
19821
19822        return fullState;
19823    }
19824
19825    /**
19826     * Merge your own state values in <var>additionalState</var> into the base
19827     * state values <var>baseState</var> that were returned by
19828     * {@link #onCreateDrawableState(int)}.
19829     *
19830     * @param baseState The base state values returned by
19831     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
19832     * own additional state values.
19833     *
19834     * @param additionalState The additional state values you would like
19835     * added to <var>baseState</var>; this array is not modified.
19836     *
19837     * @return As a convenience, the <var>baseState</var> array you originally
19838     * passed into the function is returned.
19839     *
19840     * @see #onCreateDrawableState(int)
19841     */
19842    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
19843        final int N = baseState.length;
19844        int i = N - 1;
19845        while (i >= 0 && baseState[i] == 0) {
19846            i--;
19847        }
19848        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
19849        return baseState;
19850    }
19851
19852    /**
19853     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
19854     * on all Drawable objects associated with this view.
19855     * <p>
19856     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
19857     * attached to this view.
19858     */
19859    @CallSuper
19860    public void jumpDrawablesToCurrentState() {
19861        if (mBackground != null) {
19862            mBackground.jumpToCurrentState();
19863        }
19864        if (mStateListAnimator != null) {
19865            mStateListAnimator.jumpToCurrentState();
19866        }
19867        if (mDefaultFocusHighlight != null) {
19868            mDefaultFocusHighlight.jumpToCurrentState();
19869        }
19870        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19871            mForegroundInfo.mDrawable.jumpToCurrentState();
19872        }
19873    }
19874
19875    /**
19876     * Sets the background color for this view.
19877     * @param color the color of the background
19878     */
19879    @RemotableViewMethod
19880    public void setBackgroundColor(@ColorInt int color) {
19881        if (mBackground instanceof ColorDrawable) {
19882            ((ColorDrawable) mBackground.mutate()).setColor(color);
19883            computeOpaqueFlags();
19884            mBackgroundResource = 0;
19885        } else {
19886            setBackground(new ColorDrawable(color));
19887        }
19888    }
19889
19890    /**
19891     * Set the background to a given resource. The resource should refer to
19892     * a Drawable object or 0 to remove the background.
19893     * @param resid The identifier of the resource.
19894     *
19895     * @attr ref android.R.styleable#View_background
19896     */
19897    @RemotableViewMethod
19898    public void setBackgroundResource(@DrawableRes int resid) {
19899        if (resid != 0 && resid == mBackgroundResource) {
19900            return;
19901        }
19902
19903        Drawable d = null;
19904        if (resid != 0) {
19905            d = mContext.getDrawable(resid);
19906        }
19907        setBackground(d);
19908
19909        mBackgroundResource = resid;
19910    }
19911
19912    /**
19913     * Set the background to a given Drawable, or remove the background. If the
19914     * background has padding, this View's padding is set to the background's
19915     * padding. However, when a background is removed, this View's padding isn't
19916     * touched. If setting the padding is desired, please use
19917     * {@link #setPadding(int, int, int, int)}.
19918     *
19919     * @param background The Drawable to use as the background, or null to remove the
19920     *        background
19921     */
19922    public void setBackground(Drawable background) {
19923        //noinspection deprecation
19924        setBackgroundDrawable(background);
19925    }
19926
19927    /**
19928     * @deprecated use {@link #setBackground(Drawable)} instead
19929     */
19930    @Deprecated
19931    public void setBackgroundDrawable(Drawable background) {
19932        computeOpaqueFlags();
19933
19934        if (background == mBackground) {
19935            return;
19936        }
19937
19938        boolean requestLayout = false;
19939
19940        mBackgroundResource = 0;
19941
19942        /*
19943         * Regardless of whether we're setting a new background or not, we want
19944         * to clear the previous drawable. setVisible first while we still have the callback set.
19945         */
19946        if (mBackground != null) {
19947            if (isAttachedToWindow()) {
19948                mBackground.setVisible(false, false);
19949            }
19950            mBackground.setCallback(null);
19951            unscheduleDrawable(mBackground);
19952        }
19953
19954        if (background != null) {
19955            Rect padding = sThreadLocal.get();
19956            if (padding == null) {
19957                padding = new Rect();
19958                sThreadLocal.set(padding);
19959            }
19960            resetResolvedDrawablesInternal();
19961            background.setLayoutDirection(getLayoutDirection());
19962            if (background.getPadding(padding)) {
19963                resetResolvedPaddingInternal();
19964                switch (background.getLayoutDirection()) {
19965                    case LAYOUT_DIRECTION_RTL:
19966                        mUserPaddingLeftInitial = padding.right;
19967                        mUserPaddingRightInitial = padding.left;
19968                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
19969                        break;
19970                    case LAYOUT_DIRECTION_LTR:
19971                    default:
19972                        mUserPaddingLeftInitial = padding.left;
19973                        mUserPaddingRightInitial = padding.right;
19974                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
19975                }
19976                mLeftPaddingDefined = false;
19977                mRightPaddingDefined = false;
19978            }
19979
19980            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
19981            // if it has a different minimum size, we should layout again
19982            if (mBackground == null
19983                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
19984                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
19985                requestLayout = true;
19986            }
19987
19988            // Set mBackground before we set this as the callback and start making other
19989            // background drawable state change calls. In particular, the setVisible call below
19990            // can result in drawables attempting to start animations or otherwise invalidate,
19991            // which requires the view set as the callback (us) to recognize the drawable as
19992            // belonging to it as per verifyDrawable.
19993            mBackground = background;
19994            if (background.isStateful()) {
19995                background.setState(getDrawableState());
19996            }
19997            if (isAttachedToWindow()) {
19998                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
19999            }
20000
20001            applyBackgroundTint();
20002
20003            // Set callback last, since the view may still be initializing.
20004            background.setCallback(this);
20005
20006            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20007                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20008                requestLayout = true;
20009            }
20010        } else {
20011            /* Remove the background */
20012            mBackground = null;
20013            if ((mViewFlags & WILL_NOT_DRAW) != 0
20014                    && (mDefaultFocusHighlight == null)
20015                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20016                mPrivateFlags |= PFLAG_SKIP_DRAW;
20017            }
20018
20019            /*
20020             * When the background is set, we try to apply its padding to this
20021             * View. When the background is removed, we don't touch this View's
20022             * padding. This is noted in the Javadocs. Hence, we don't need to
20023             * requestLayout(), the invalidate() below is sufficient.
20024             */
20025
20026            // The old background's minimum size could have affected this
20027            // View's layout, so let's requestLayout
20028            requestLayout = true;
20029        }
20030
20031        computeOpaqueFlags();
20032
20033        if (requestLayout) {
20034            requestLayout();
20035        }
20036
20037        mBackgroundSizeChanged = true;
20038        invalidate(true);
20039        invalidateOutline();
20040    }
20041
20042    /**
20043     * Gets the background drawable
20044     *
20045     * @return The drawable used as the background for this view, if any.
20046     *
20047     * @see #setBackground(Drawable)
20048     *
20049     * @attr ref android.R.styleable#View_background
20050     */
20051    public Drawable getBackground() {
20052        return mBackground;
20053    }
20054
20055    /**
20056     * Applies a tint to the background drawable. Does not modify the current tint
20057     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20058     * <p>
20059     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
20060     * mutate the drawable and apply the specified tint and tint mode using
20061     * {@link Drawable#setTintList(ColorStateList)}.
20062     *
20063     * @param tint the tint to apply, may be {@code null} to clear tint
20064     *
20065     * @attr ref android.R.styleable#View_backgroundTint
20066     * @see #getBackgroundTintList()
20067     * @see Drawable#setTintList(ColorStateList)
20068     */
20069    public void setBackgroundTintList(@Nullable ColorStateList tint) {
20070        if (mBackgroundTint == null) {
20071            mBackgroundTint = new TintInfo();
20072        }
20073        mBackgroundTint.mTintList = tint;
20074        mBackgroundTint.mHasTintList = true;
20075
20076        applyBackgroundTint();
20077    }
20078
20079    /**
20080     * Return the tint applied to the background drawable, if specified.
20081     *
20082     * @return the tint applied to the background drawable
20083     * @attr ref android.R.styleable#View_backgroundTint
20084     * @see #setBackgroundTintList(ColorStateList)
20085     */
20086    @Nullable
20087    public ColorStateList getBackgroundTintList() {
20088        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
20089    }
20090
20091    /**
20092     * Specifies the blending mode used to apply the tint specified by
20093     * {@link #setBackgroundTintList(ColorStateList)}} to the background
20094     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20095     *
20096     * @param tintMode the blending mode used to apply the tint, may be
20097     *                 {@code null} to clear tint
20098     * @attr ref android.R.styleable#View_backgroundTintMode
20099     * @see #getBackgroundTintMode()
20100     * @see Drawable#setTintMode(PorterDuff.Mode)
20101     */
20102    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20103        if (mBackgroundTint == null) {
20104            mBackgroundTint = new TintInfo();
20105        }
20106        mBackgroundTint.mTintMode = tintMode;
20107        mBackgroundTint.mHasTintMode = true;
20108
20109        applyBackgroundTint();
20110    }
20111
20112    /**
20113     * Return the blending mode used to apply the tint to the background
20114     * drawable, if specified.
20115     *
20116     * @return the blending mode used to apply the tint to the background
20117     *         drawable
20118     * @attr ref android.R.styleable#View_backgroundTintMode
20119     * @see #setBackgroundTintMode(PorterDuff.Mode)
20120     */
20121    @Nullable
20122    public PorterDuff.Mode getBackgroundTintMode() {
20123        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
20124    }
20125
20126    private void applyBackgroundTint() {
20127        if (mBackground != null && mBackgroundTint != null) {
20128            final TintInfo tintInfo = mBackgroundTint;
20129            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20130                mBackground = mBackground.mutate();
20131
20132                if (tintInfo.mHasTintList) {
20133                    mBackground.setTintList(tintInfo.mTintList);
20134                }
20135
20136                if (tintInfo.mHasTintMode) {
20137                    mBackground.setTintMode(tintInfo.mTintMode);
20138                }
20139
20140                // The drawable (or one of its children) may not have been
20141                // stateful before applying the tint, so let's try again.
20142                if (mBackground.isStateful()) {
20143                    mBackground.setState(getDrawableState());
20144                }
20145            }
20146        }
20147    }
20148
20149    /**
20150     * Returns the drawable used as the foreground of this View. The
20151     * foreground drawable, if non-null, is always drawn on top of the view's content.
20152     *
20153     * @return a Drawable or null if no foreground was set
20154     *
20155     * @see #onDrawForeground(Canvas)
20156     */
20157    public Drawable getForeground() {
20158        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20159    }
20160
20161    /**
20162     * Supply a Drawable that is to be rendered on top of all of the content in the view.
20163     *
20164     * @param foreground the Drawable to be drawn on top of the children
20165     *
20166     * @attr ref android.R.styleable#View_foreground
20167     */
20168    public void setForeground(Drawable foreground) {
20169        if (mForegroundInfo == null) {
20170            if (foreground == null) {
20171                // Nothing to do.
20172                return;
20173            }
20174            mForegroundInfo = new ForegroundInfo();
20175        }
20176
20177        if (foreground == mForegroundInfo.mDrawable) {
20178            // Nothing to do
20179            return;
20180        }
20181
20182        if (mForegroundInfo.mDrawable != null) {
20183            if (isAttachedToWindow()) {
20184                mForegroundInfo.mDrawable.setVisible(false, false);
20185            }
20186            mForegroundInfo.mDrawable.setCallback(null);
20187            unscheduleDrawable(mForegroundInfo.mDrawable);
20188        }
20189
20190        mForegroundInfo.mDrawable = foreground;
20191        mForegroundInfo.mBoundsChanged = true;
20192        if (foreground != null) {
20193            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20194                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20195            }
20196            foreground.setLayoutDirection(getLayoutDirection());
20197            if (foreground.isStateful()) {
20198                foreground.setState(getDrawableState());
20199            }
20200            applyForegroundTint();
20201            if (isAttachedToWindow()) {
20202                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20203            }
20204            // Set callback last, since the view may still be initializing.
20205            foreground.setCallback(this);
20206        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20207                && (mDefaultFocusHighlight == null)) {
20208            mPrivateFlags |= PFLAG_SKIP_DRAW;
20209        }
20210        requestLayout();
20211        invalidate();
20212    }
20213
20214    /**
20215     * Magic bit used to support features of framework-internal window decor implementation details.
20216     * This used to live exclusively in FrameLayout.
20217     *
20218     * @return true if the foreground should draw inside the padding region or false
20219     *         if it should draw inset by the view's padding
20220     * @hide internal use only; only used by FrameLayout and internal screen layouts.
20221     */
20222    public boolean isForegroundInsidePadding() {
20223        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
20224    }
20225
20226    /**
20227     * Describes how the foreground is positioned.
20228     *
20229     * @return foreground gravity.
20230     *
20231     * @see #setForegroundGravity(int)
20232     *
20233     * @attr ref android.R.styleable#View_foregroundGravity
20234     */
20235    public int getForegroundGravity() {
20236        return mForegroundInfo != null ? mForegroundInfo.mGravity
20237                : Gravity.START | Gravity.TOP;
20238    }
20239
20240    /**
20241     * Describes how the foreground is positioned. Defaults to START and TOP.
20242     *
20243     * @param gravity see {@link android.view.Gravity}
20244     *
20245     * @see #getForegroundGravity()
20246     *
20247     * @attr ref android.R.styleable#View_foregroundGravity
20248     */
20249    public void setForegroundGravity(int gravity) {
20250        if (mForegroundInfo == null) {
20251            mForegroundInfo = new ForegroundInfo();
20252        }
20253
20254        if (mForegroundInfo.mGravity != gravity) {
20255            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20256                gravity |= Gravity.START;
20257            }
20258
20259            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20260                gravity |= Gravity.TOP;
20261            }
20262
20263            mForegroundInfo.mGravity = gravity;
20264            requestLayout();
20265        }
20266    }
20267
20268    /**
20269     * Applies a tint to the foreground drawable. Does not modify the current tint
20270     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20271     * <p>
20272     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20273     * mutate the drawable and apply the specified tint and tint mode using
20274     * {@link Drawable#setTintList(ColorStateList)}.
20275     *
20276     * @param tint the tint to apply, may be {@code null} to clear tint
20277     *
20278     * @attr ref android.R.styleable#View_foregroundTint
20279     * @see #getForegroundTintList()
20280     * @see Drawable#setTintList(ColorStateList)
20281     */
20282    public void setForegroundTintList(@Nullable ColorStateList tint) {
20283        if (mForegroundInfo == null) {
20284            mForegroundInfo = new ForegroundInfo();
20285        }
20286        if (mForegroundInfo.mTintInfo == null) {
20287            mForegroundInfo.mTintInfo = new TintInfo();
20288        }
20289        mForegroundInfo.mTintInfo.mTintList = tint;
20290        mForegroundInfo.mTintInfo.mHasTintList = true;
20291
20292        applyForegroundTint();
20293    }
20294
20295    /**
20296     * Return the tint applied to the foreground drawable, if specified.
20297     *
20298     * @return the tint applied to the foreground drawable
20299     * @attr ref android.R.styleable#View_foregroundTint
20300     * @see #setForegroundTintList(ColorStateList)
20301     */
20302    @Nullable
20303    public ColorStateList getForegroundTintList() {
20304        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20305                ? mForegroundInfo.mTintInfo.mTintList : null;
20306    }
20307
20308    /**
20309     * Specifies the blending mode used to apply the tint specified by
20310     * {@link #setForegroundTintList(ColorStateList)}} to the background
20311     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20312     *
20313     * @param tintMode the blending mode used to apply the tint, may be
20314     *                 {@code null} to clear tint
20315     * @attr ref android.R.styleable#View_foregroundTintMode
20316     * @see #getForegroundTintMode()
20317     * @see Drawable#setTintMode(PorterDuff.Mode)
20318     */
20319    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20320        if (mForegroundInfo == null) {
20321            mForegroundInfo = new ForegroundInfo();
20322        }
20323        if (mForegroundInfo.mTintInfo == null) {
20324            mForegroundInfo.mTintInfo = new TintInfo();
20325        }
20326        mForegroundInfo.mTintInfo.mTintMode = tintMode;
20327        mForegroundInfo.mTintInfo.mHasTintMode = true;
20328
20329        applyForegroundTint();
20330    }
20331
20332    /**
20333     * Return the blending mode used to apply the tint to the foreground
20334     * drawable, if specified.
20335     *
20336     * @return the blending mode used to apply the tint to the foreground
20337     *         drawable
20338     * @attr ref android.R.styleable#View_foregroundTintMode
20339     * @see #setForegroundTintMode(PorterDuff.Mode)
20340     */
20341    @Nullable
20342    public PorterDuff.Mode getForegroundTintMode() {
20343        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20344                ? mForegroundInfo.mTintInfo.mTintMode : null;
20345    }
20346
20347    private void applyForegroundTint() {
20348        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20349                && mForegroundInfo.mTintInfo != null) {
20350            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20351            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20352                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20353
20354                if (tintInfo.mHasTintList) {
20355                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20356                }
20357
20358                if (tintInfo.mHasTintMode) {
20359                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20360                }
20361
20362                // The drawable (or one of its children) may not have been
20363                // stateful before applying the tint, so let's try again.
20364                if (mForegroundInfo.mDrawable.isStateful()) {
20365                    mForegroundInfo.mDrawable.setState(getDrawableState());
20366                }
20367            }
20368        }
20369    }
20370
20371    /**
20372     * Get the drawable to be overlayed when a view is autofilled
20373     *
20374     * @return The drawable
20375     *
20376     * @throws IllegalStateException if the drawable could not be found.
20377     */
20378    @NonNull private Drawable getAutofilledDrawable() {
20379        // Lazily load the isAutofilled drawable.
20380        if (mAttachInfo.mAutofilledDrawable == null) {
20381            mAttachInfo.mAutofilledDrawable = mContext.getDrawable(R.drawable.autofilled_highlight);
20382
20383            if (mAttachInfo.mAutofilledDrawable == null) {
20384                throw new IllegalStateException(
20385                        "Could not find android:drawable/autofilled_highlight");
20386            }
20387        }
20388
20389        return mAttachInfo.mAutofilledDrawable;
20390    }
20391
20392    /**
20393     * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
20394     *
20395     * @param canvas The canvas to draw on
20396     */
20397    private void drawAutofilledHighlight(@NonNull Canvas canvas) {
20398        if (isAutofilled()) {
20399            Drawable autofilledHighlight = getAutofilledDrawable();
20400
20401            autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
20402            autofilledHighlight.draw(canvas);
20403        }
20404    }
20405
20406    /**
20407     * Draw any foreground content for this view.
20408     *
20409     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20410     * drawable or other view-specific decorations. The foreground is drawn on top of the
20411     * primary view content.</p>
20412     *
20413     * @param canvas canvas to draw into
20414     */
20415    public void onDrawForeground(Canvas canvas) {
20416        onDrawScrollIndicators(canvas);
20417        onDrawScrollBars(canvas);
20418
20419        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20420        if (foreground != null) {
20421            if (mForegroundInfo.mBoundsChanged) {
20422                mForegroundInfo.mBoundsChanged = false;
20423                final Rect selfBounds = mForegroundInfo.mSelfBounds;
20424                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20425
20426                if (mForegroundInfo.mInsidePadding) {
20427                    selfBounds.set(0, 0, getWidth(), getHeight());
20428                } else {
20429                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
20430                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20431                }
20432
20433                final int ld = getLayoutDirection();
20434                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20435                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20436                foreground.setBounds(overlayBounds);
20437            }
20438
20439            foreground.draw(canvas);
20440        }
20441    }
20442
20443    /**
20444     * Sets the padding. The view may add on the space required to display
20445     * the scrollbars, depending on the style and visibility of the scrollbars.
20446     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20447     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20448     * from the values set in this call.
20449     *
20450     * @attr ref android.R.styleable#View_padding
20451     * @attr ref android.R.styleable#View_paddingBottom
20452     * @attr ref android.R.styleable#View_paddingLeft
20453     * @attr ref android.R.styleable#View_paddingRight
20454     * @attr ref android.R.styleable#View_paddingTop
20455     * @param left the left padding in pixels
20456     * @param top the top padding in pixels
20457     * @param right the right padding in pixels
20458     * @param bottom the bottom padding in pixels
20459     */
20460    public void setPadding(int left, int top, int right, int bottom) {
20461        resetResolvedPaddingInternal();
20462
20463        mUserPaddingStart = UNDEFINED_PADDING;
20464        mUserPaddingEnd = UNDEFINED_PADDING;
20465
20466        mUserPaddingLeftInitial = left;
20467        mUserPaddingRightInitial = right;
20468
20469        mLeftPaddingDefined = true;
20470        mRightPaddingDefined = true;
20471
20472        internalSetPadding(left, top, right, bottom);
20473    }
20474
20475    /**
20476     * @hide
20477     */
20478    protected void internalSetPadding(int left, int top, int right, int bottom) {
20479        mUserPaddingLeft = left;
20480        mUserPaddingRight = right;
20481        mUserPaddingBottom = bottom;
20482
20483        final int viewFlags = mViewFlags;
20484        boolean changed = false;
20485
20486        // Common case is there are no scroll bars.
20487        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20488            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20489                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20490                        ? 0 : getVerticalScrollbarWidth();
20491                switch (mVerticalScrollbarPosition) {
20492                    case SCROLLBAR_POSITION_DEFAULT:
20493                        if (isLayoutRtl()) {
20494                            left += offset;
20495                        } else {
20496                            right += offset;
20497                        }
20498                        break;
20499                    case SCROLLBAR_POSITION_RIGHT:
20500                        right += offset;
20501                        break;
20502                    case SCROLLBAR_POSITION_LEFT:
20503                        left += offset;
20504                        break;
20505                }
20506            }
20507            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20508                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20509                        ? 0 : getHorizontalScrollbarHeight();
20510            }
20511        }
20512
20513        if (mPaddingLeft != left) {
20514            changed = true;
20515            mPaddingLeft = left;
20516        }
20517        if (mPaddingTop != top) {
20518            changed = true;
20519            mPaddingTop = top;
20520        }
20521        if (mPaddingRight != right) {
20522            changed = true;
20523            mPaddingRight = right;
20524        }
20525        if (mPaddingBottom != bottom) {
20526            changed = true;
20527            mPaddingBottom = bottom;
20528        }
20529
20530        if (changed) {
20531            requestLayout();
20532            invalidateOutline();
20533        }
20534    }
20535
20536    /**
20537     * Sets the relative padding. The view may add on the space required to display
20538     * the scrollbars, depending on the style and visibility of the scrollbars.
20539     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
20540     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
20541     * from the values set in this call.
20542     *
20543     * @attr ref android.R.styleable#View_padding
20544     * @attr ref android.R.styleable#View_paddingBottom
20545     * @attr ref android.R.styleable#View_paddingStart
20546     * @attr ref android.R.styleable#View_paddingEnd
20547     * @attr ref android.R.styleable#View_paddingTop
20548     * @param start the start padding in pixels
20549     * @param top the top padding in pixels
20550     * @param end the end padding in pixels
20551     * @param bottom the bottom padding in pixels
20552     */
20553    public void setPaddingRelative(int start, int top, int end, int bottom) {
20554        resetResolvedPaddingInternal();
20555
20556        mUserPaddingStart = start;
20557        mUserPaddingEnd = end;
20558        mLeftPaddingDefined = true;
20559        mRightPaddingDefined = true;
20560
20561        switch(getLayoutDirection()) {
20562            case LAYOUT_DIRECTION_RTL:
20563                mUserPaddingLeftInitial = end;
20564                mUserPaddingRightInitial = start;
20565                internalSetPadding(end, top, start, bottom);
20566                break;
20567            case LAYOUT_DIRECTION_LTR:
20568            default:
20569                mUserPaddingLeftInitial = start;
20570                mUserPaddingRightInitial = end;
20571                internalSetPadding(start, top, end, bottom);
20572        }
20573    }
20574
20575    /**
20576     * Returns the top padding of this view.
20577     *
20578     * @return the top padding in pixels
20579     */
20580    public int getPaddingTop() {
20581        return mPaddingTop;
20582    }
20583
20584    /**
20585     * Returns the bottom padding of this view. If there are inset and enabled
20586     * scrollbars, this value may include the space required to display the
20587     * scrollbars as well.
20588     *
20589     * @return the bottom padding in pixels
20590     */
20591    public int getPaddingBottom() {
20592        return mPaddingBottom;
20593    }
20594
20595    /**
20596     * Returns the left padding of this view. If there are inset and enabled
20597     * scrollbars, this value may include the space required to display the
20598     * scrollbars as well.
20599     *
20600     * @return the left padding in pixels
20601     */
20602    public int getPaddingLeft() {
20603        if (!isPaddingResolved()) {
20604            resolvePadding();
20605        }
20606        return mPaddingLeft;
20607    }
20608
20609    /**
20610     * Returns the start padding of this view depending on its resolved layout direction.
20611     * If there are inset and enabled scrollbars, this value may include the space
20612     * required to display the scrollbars as well.
20613     *
20614     * @return the start padding in pixels
20615     */
20616    public int getPaddingStart() {
20617        if (!isPaddingResolved()) {
20618            resolvePadding();
20619        }
20620        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20621                mPaddingRight : mPaddingLeft;
20622    }
20623
20624    /**
20625     * Returns the right padding of this view. If there are inset and enabled
20626     * scrollbars, this value may include the space required to display the
20627     * scrollbars as well.
20628     *
20629     * @return the right padding in pixels
20630     */
20631    public int getPaddingRight() {
20632        if (!isPaddingResolved()) {
20633            resolvePadding();
20634        }
20635        return mPaddingRight;
20636    }
20637
20638    /**
20639     * Returns the end padding of this view depending on its resolved layout direction.
20640     * If there are inset and enabled scrollbars, this value may include the space
20641     * required to display the scrollbars as well.
20642     *
20643     * @return the end padding in pixels
20644     */
20645    public int getPaddingEnd() {
20646        if (!isPaddingResolved()) {
20647            resolvePadding();
20648        }
20649        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
20650                mPaddingLeft : mPaddingRight;
20651    }
20652
20653    /**
20654     * Return if the padding has been set through relative values
20655     * {@link #setPaddingRelative(int, int, int, int)} or through
20656     * @attr ref android.R.styleable#View_paddingStart or
20657     * @attr ref android.R.styleable#View_paddingEnd
20658     *
20659     * @return true if the padding is relative or false if it is not.
20660     */
20661    public boolean isPaddingRelative() {
20662        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
20663    }
20664
20665    Insets computeOpticalInsets() {
20666        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
20667    }
20668
20669    /**
20670     * @hide
20671     */
20672    public void resetPaddingToInitialValues() {
20673        if (isRtlCompatibilityMode()) {
20674            mPaddingLeft = mUserPaddingLeftInitial;
20675            mPaddingRight = mUserPaddingRightInitial;
20676            return;
20677        }
20678        if (isLayoutRtl()) {
20679            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
20680            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
20681        } else {
20682            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
20683            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
20684        }
20685    }
20686
20687    /**
20688     * @hide
20689     */
20690    public Insets getOpticalInsets() {
20691        if (mLayoutInsets == null) {
20692            mLayoutInsets = computeOpticalInsets();
20693        }
20694        return mLayoutInsets;
20695    }
20696
20697    /**
20698     * Set this view's optical insets.
20699     *
20700     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
20701     * property. Views that compute their own optical insets should call it as part of measurement.
20702     * This method does not request layout. If you are setting optical insets outside of
20703     * measure/layout itself you will want to call requestLayout() yourself.
20704     * </p>
20705     * @hide
20706     */
20707    public void setOpticalInsets(Insets insets) {
20708        mLayoutInsets = insets;
20709    }
20710
20711    /**
20712     * Changes the selection state of this view. A view can be selected or not.
20713     * Note that selection is not the same as focus. Views are typically
20714     * selected in the context of an AdapterView like ListView or GridView;
20715     * the selected view is the view that is highlighted.
20716     *
20717     * @param selected true if the view must be selected, false otherwise
20718     */
20719    public void setSelected(boolean selected) {
20720        //noinspection DoubleNegation
20721        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
20722            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
20723            if (!selected) resetPressedState();
20724            invalidate(true);
20725            refreshDrawableState();
20726            dispatchSetSelected(selected);
20727            if (selected) {
20728                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
20729            } else {
20730                notifyViewAccessibilityStateChangedIfNeeded(
20731                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
20732            }
20733        }
20734    }
20735
20736    /**
20737     * Dispatch setSelected to all of this View's children.
20738     *
20739     * @see #setSelected(boolean)
20740     *
20741     * @param selected The new selected state
20742     */
20743    protected void dispatchSetSelected(boolean selected) {
20744    }
20745
20746    /**
20747     * Indicates the selection state of this view.
20748     *
20749     * @return true if the view is selected, false otherwise
20750     */
20751    @ViewDebug.ExportedProperty
20752    public boolean isSelected() {
20753        return (mPrivateFlags & PFLAG_SELECTED) != 0;
20754    }
20755
20756    /**
20757     * Changes the activated state of this view. A view can be activated or not.
20758     * Note that activation is not the same as selection.  Selection is
20759     * a transient property, representing the view (hierarchy) the user is
20760     * currently interacting with.  Activation is a longer-term state that the
20761     * user can move views in and out of.  For example, in a list view with
20762     * single or multiple selection enabled, the views in the current selection
20763     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
20764     * here.)  The activated state is propagated down to children of the view it
20765     * is set on.
20766     *
20767     * @param activated true if the view must be activated, false otherwise
20768     */
20769    public void setActivated(boolean activated) {
20770        //noinspection DoubleNegation
20771        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
20772            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
20773            invalidate(true);
20774            refreshDrawableState();
20775            dispatchSetActivated(activated);
20776        }
20777    }
20778
20779    /**
20780     * Dispatch setActivated to all of this View's children.
20781     *
20782     * @see #setActivated(boolean)
20783     *
20784     * @param activated The new activated state
20785     */
20786    protected void dispatchSetActivated(boolean activated) {
20787    }
20788
20789    /**
20790     * Indicates the activation state of this view.
20791     *
20792     * @return true if the view is activated, false otherwise
20793     */
20794    @ViewDebug.ExportedProperty
20795    public boolean isActivated() {
20796        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
20797    }
20798
20799    /**
20800     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
20801     * observer can be used to get notifications when global events, like
20802     * layout, happen.
20803     *
20804     * The returned ViewTreeObserver observer is not guaranteed to remain
20805     * valid for the lifetime of this View. If the caller of this method keeps
20806     * a long-lived reference to ViewTreeObserver, it should always check for
20807     * the return value of {@link ViewTreeObserver#isAlive()}.
20808     *
20809     * @return The ViewTreeObserver for this view's hierarchy.
20810     */
20811    public ViewTreeObserver getViewTreeObserver() {
20812        if (mAttachInfo != null) {
20813            return mAttachInfo.mTreeObserver;
20814        }
20815        if (mFloatingTreeObserver == null) {
20816            mFloatingTreeObserver = new ViewTreeObserver(mContext);
20817        }
20818        return mFloatingTreeObserver;
20819    }
20820
20821    /**
20822     * <p>Finds the topmost view in the current view hierarchy.</p>
20823     *
20824     * @return the topmost view containing this view
20825     */
20826    public View getRootView() {
20827        if (mAttachInfo != null) {
20828            final View v = mAttachInfo.mRootView;
20829            if (v != null) {
20830                return v;
20831            }
20832        }
20833
20834        View parent = this;
20835
20836        while (parent.mParent != null && parent.mParent instanceof View) {
20837            parent = (View) parent.mParent;
20838        }
20839
20840        return parent;
20841    }
20842
20843    /**
20844     * Transforms a motion event from view-local coordinates to on-screen
20845     * coordinates.
20846     *
20847     * @param ev the view-local motion event
20848     * @return false if the transformation could not be applied
20849     * @hide
20850     */
20851    public boolean toGlobalMotionEvent(MotionEvent ev) {
20852        final AttachInfo info = mAttachInfo;
20853        if (info == null) {
20854            return false;
20855        }
20856
20857        final Matrix m = info.mTmpMatrix;
20858        m.set(Matrix.IDENTITY_MATRIX);
20859        transformMatrixToGlobal(m);
20860        ev.transform(m);
20861        return true;
20862    }
20863
20864    /**
20865     * Transforms a motion event from on-screen coordinates to view-local
20866     * coordinates.
20867     *
20868     * @param ev the on-screen motion event
20869     * @return false if the transformation could not be applied
20870     * @hide
20871     */
20872    public boolean toLocalMotionEvent(MotionEvent ev) {
20873        final AttachInfo info = mAttachInfo;
20874        if (info == null) {
20875            return false;
20876        }
20877
20878        final Matrix m = info.mTmpMatrix;
20879        m.set(Matrix.IDENTITY_MATRIX);
20880        transformMatrixToLocal(m);
20881        ev.transform(m);
20882        return true;
20883    }
20884
20885    /**
20886     * Modifies the input matrix such that it maps view-local coordinates to
20887     * on-screen coordinates.
20888     *
20889     * @param m input matrix to modify
20890     * @hide
20891     */
20892    public void transformMatrixToGlobal(Matrix m) {
20893        final ViewParent parent = mParent;
20894        if (parent instanceof View) {
20895            final View vp = (View) parent;
20896            vp.transformMatrixToGlobal(m);
20897            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
20898        } else if (parent instanceof ViewRootImpl) {
20899            final ViewRootImpl vr = (ViewRootImpl) parent;
20900            vr.transformMatrixToGlobal(m);
20901            m.preTranslate(0, -vr.mCurScrollY);
20902        }
20903
20904        m.preTranslate(mLeft, mTop);
20905
20906        if (!hasIdentityMatrix()) {
20907            m.preConcat(getMatrix());
20908        }
20909    }
20910
20911    /**
20912     * Modifies the input matrix such that it maps on-screen coordinates to
20913     * view-local coordinates.
20914     *
20915     * @param m input matrix to modify
20916     * @hide
20917     */
20918    public void transformMatrixToLocal(Matrix m) {
20919        final ViewParent parent = mParent;
20920        if (parent instanceof View) {
20921            final View vp = (View) parent;
20922            vp.transformMatrixToLocal(m);
20923            m.postTranslate(vp.mScrollX, vp.mScrollY);
20924        } else if (parent instanceof ViewRootImpl) {
20925            final ViewRootImpl vr = (ViewRootImpl) parent;
20926            vr.transformMatrixToLocal(m);
20927            m.postTranslate(0, vr.mCurScrollY);
20928        }
20929
20930        m.postTranslate(-mLeft, -mTop);
20931
20932        if (!hasIdentityMatrix()) {
20933            m.postConcat(getInverseMatrix());
20934        }
20935    }
20936
20937    /**
20938     * @hide
20939     */
20940    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
20941            @ViewDebug.IntToString(from = 0, to = "x"),
20942            @ViewDebug.IntToString(from = 1, to = "y")
20943    })
20944    public int[] getLocationOnScreen() {
20945        int[] location = new int[2];
20946        getLocationOnScreen(location);
20947        return location;
20948    }
20949
20950    /**
20951     * <p>Computes the coordinates of this view on the screen. The argument
20952     * must be an array of two integers. After the method returns, the array
20953     * contains the x and y location in that order.</p>
20954     *
20955     * @param outLocation an array of two integers in which to hold the coordinates
20956     */
20957    public void getLocationOnScreen(@Size(2) int[] outLocation) {
20958        getLocationInWindow(outLocation);
20959
20960        final AttachInfo info = mAttachInfo;
20961        if (info != null) {
20962            outLocation[0] += info.mWindowLeft;
20963            outLocation[1] += info.mWindowTop;
20964        }
20965    }
20966
20967    /**
20968     * <p>Computes the coordinates of this view in its window. The argument
20969     * must be an array of two integers. After the method returns, the array
20970     * contains the x and y location in that order.</p>
20971     *
20972     * @param outLocation an array of two integers in which to hold the coordinates
20973     */
20974    public void getLocationInWindow(@Size(2) int[] outLocation) {
20975        if (outLocation == null || outLocation.length < 2) {
20976            throw new IllegalArgumentException("outLocation must be an array of two integers");
20977        }
20978
20979        outLocation[0] = 0;
20980        outLocation[1] = 0;
20981
20982        transformFromViewToWindowSpace(outLocation);
20983    }
20984
20985    /** @hide */
20986    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
20987        if (inOutLocation == null || inOutLocation.length < 2) {
20988            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
20989        }
20990
20991        if (mAttachInfo == null) {
20992            // When the view is not attached to a window, this method does not make sense
20993            inOutLocation[0] = inOutLocation[1] = 0;
20994            return;
20995        }
20996
20997        float position[] = mAttachInfo.mTmpTransformLocation;
20998        position[0] = inOutLocation[0];
20999        position[1] = inOutLocation[1];
21000
21001        if (!hasIdentityMatrix()) {
21002            getMatrix().mapPoints(position);
21003        }
21004
21005        position[0] += mLeft;
21006        position[1] += mTop;
21007
21008        ViewParent viewParent = mParent;
21009        while (viewParent instanceof View) {
21010            final View view = (View) viewParent;
21011
21012            position[0] -= view.mScrollX;
21013            position[1] -= view.mScrollY;
21014
21015            if (!view.hasIdentityMatrix()) {
21016                view.getMatrix().mapPoints(position);
21017            }
21018
21019            position[0] += view.mLeft;
21020            position[1] += view.mTop;
21021
21022            viewParent = view.mParent;
21023         }
21024
21025        if (viewParent instanceof ViewRootImpl) {
21026            // *cough*
21027            final ViewRootImpl vr = (ViewRootImpl) viewParent;
21028            position[1] -= vr.mCurScrollY;
21029        }
21030
21031        inOutLocation[0] = Math.round(position[0]);
21032        inOutLocation[1] = Math.round(position[1]);
21033    }
21034
21035    /**
21036     * @param id the id of the view to be found
21037     * @return the view of the specified id, null if cannot be found
21038     * @hide
21039     */
21040    protected <T extends View> T findViewTraversal(@IdRes int id) {
21041        if (id == mID) {
21042            return (T) this;
21043        }
21044        return null;
21045    }
21046
21047    /**
21048     * @param tag the tag of the view to be found
21049     * @return the view of specified tag, null if cannot be found
21050     * @hide
21051     */
21052    protected <T extends View> T findViewWithTagTraversal(Object tag) {
21053        if (tag != null && tag.equals(mTag)) {
21054            return (T) this;
21055        }
21056        return null;
21057    }
21058
21059    /**
21060     * @param predicate The predicate to evaluate.
21061     * @param childToSkip If not null, ignores this child during the recursive traversal.
21062     * @return The first view that matches the predicate or null.
21063     * @hide
21064     */
21065    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
21066            View childToSkip) {
21067        if (predicate.test(this)) {
21068            return (T) this;
21069        }
21070        return null;
21071    }
21072
21073    /**
21074     * Finds the first descendant view with the given ID, the view itself if
21075     * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
21076     * (< 0) or there is no matching view in the hierarchy.
21077     * <p>
21078     * <strong>Note:</strong> In most cases -- depending on compiler support --
21079     * the resulting view is automatically cast to the target class type. If
21080     * the target class type is unconstrained, an explicit cast may be
21081     * necessary.
21082     *
21083     * @param id the ID to search for
21084     * @return a view with given ID if found, or {@code null} otherwise
21085     * @see View#findViewById(int)
21086     */
21087    @Nullable
21088    public final <T extends View> T findViewById(@IdRes int id) {
21089        if (id < 0) {
21090            return null;
21091        }
21092        return findViewTraversal(id);
21093    }
21094
21095    /**
21096     * Finds a view by its unuque and stable accessibility id.
21097     *
21098     * @param accessibilityId The searched accessibility id.
21099     * @return The found view.
21100     */
21101    final <T extends View> T  findViewByAccessibilityId(int accessibilityId) {
21102        if (accessibilityId < 0) {
21103            return null;
21104        }
21105        T view = findViewByAccessibilityIdTraversal(accessibilityId);
21106        if (view != null) {
21107            return view.includeForAccessibility() ? view : null;
21108        }
21109        return null;
21110    }
21111
21112    /**
21113     * Performs the traversal to find a view by its unuque and stable accessibility id.
21114     *
21115     * <strong>Note:</strong>This method does not stop at the root namespace
21116     * boundary since the user can touch the screen at an arbitrary location
21117     * potentially crossing the root namespace bounday which will send an
21118     * accessibility event to accessibility services and they should be able
21119     * to obtain the event source. Also accessibility ids are guaranteed to be
21120     * unique in the window.
21121     *
21122     * @param accessibilityId The accessibility id.
21123     * @return The found view.
21124     * @hide
21125     */
21126    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
21127        if (getAccessibilityViewId() == accessibilityId) {
21128            return (T) this;
21129        }
21130        return null;
21131    }
21132
21133    /**
21134     * Look for a child view with the given tag.  If this view has the given
21135     * tag, return this view.
21136     *
21137     * @param tag The tag to search for, using "tag.equals(getTag())".
21138     * @return The View that has the given tag in the hierarchy or null
21139     */
21140    public final <T extends View> T findViewWithTag(Object tag) {
21141        if (tag == null) {
21142            return null;
21143        }
21144        return findViewWithTagTraversal(tag);
21145    }
21146
21147    /**
21148     * Look for a child view that matches the specified predicate.
21149     * If this view matches the predicate, return this view.
21150     *
21151     * @param predicate The predicate to evaluate.
21152     * @return The first view that matches the predicate or null.
21153     * @hide
21154     */
21155    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
21156        return findViewByPredicateTraversal(predicate, null);
21157    }
21158
21159    /**
21160     * Look for a child view that matches the specified predicate,
21161     * starting with the specified view and its descendents and then
21162     * recusively searching the ancestors and siblings of that view
21163     * until this view is reached.
21164     *
21165     * This method is useful in cases where the predicate does not match
21166     * a single unique view (perhaps multiple views use the same id)
21167     * and we are trying to find the view that is "closest" in scope to the
21168     * starting view.
21169     *
21170     * @param start The view to start from.
21171     * @param predicate The predicate to evaluate.
21172     * @return The first view that matches the predicate or null.
21173     * @hide
21174     */
21175    public final <T extends View> T findViewByPredicateInsideOut(
21176            View start, Predicate<View> predicate) {
21177        View childToSkip = null;
21178        for (;;) {
21179            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
21180            if (view != null || start == this) {
21181                return view;
21182            }
21183
21184            ViewParent parent = start.getParent();
21185            if (parent == null || !(parent instanceof View)) {
21186                return null;
21187            }
21188
21189            childToSkip = start;
21190            start = (View) parent;
21191        }
21192    }
21193
21194    /**
21195     * Sets the identifier for this view. The identifier does not have to be
21196     * unique in this view's hierarchy. The identifier should be a positive
21197     * number.
21198     *
21199     * @see #NO_ID
21200     * @see #getId()
21201     * @see #findViewById(int)
21202     *
21203     * @param id a number used to identify the view
21204     *
21205     * @attr ref android.R.styleable#View_id
21206     */
21207    public void setId(@IdRes int id) {
21208        mID = id;
21209        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
21210            mID = generateViewId();
21211        }
21212    }
21213
21214    /**
21215     * {@hide}
21216     *
21217     * @param isRoot true if the view belongs to the root namespace, false
21218     *        otherwise
21219     */
21220    public void setIsRootNamespace(boolean isRoot) {
21221        if (isRoot) {
21222            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
21223        } else {
21224            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
21225        }
21226    }
21227
21228    /**
21229     * {@hide}
21230     *
21231     * @return true if the view belongs to the root namespace, false otherwise
21232     */
21233    public boolean isRootNamespace() {
21234        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
21235    }
21236
21237    /**
21238     * Returns this view's identifier.
21239     *
21240     * @return a positive integer used to identify the view or {@link #NO_ID}
21241     *         if the view has no ID
21242     *
21243     * @see #setId(int)
21244     * @see #findViewById(int)
21245     * @attr ref android.R.styleable#View_id
21246     */
21247    @IdRes
21248    @ViewDebug.CapturedViewProperty
21249    public int getId() {
21250        return mID;
21251    }
21252
21253    /**
21254     * Returns this view's tag.
21255     *
21256     * @return the Object stored in this view as a tag, or {@code null} if not
21257     *         set
21258     *
21259     * @see #setTag(Object)
21260     * @see #getTag(int)
21261     */
21262    @ViewDebug.ExportedProperty
21263    public Object getTag() {
21264        return mTag;
21265    }
21266
21267    /**
21268     * Sets the tag associated with this view. A tag can be used to mark
21269     * a view in its hierarchy and does not have to be unique within the
21270     * hierarchy. Tags can also be used to store data within a view without
21271     * resorting to another data structure.
21272     *
21273     * @param tag an Object to tag the view with
21274     *
21275     * @see #getTag()
21276     * @see #setTag(int, Object)
21277     */
21278    public void setTag(final Object tag) {
21279        mTag = tag;
21280    }
21281
21282    /**
21283     * Returns the tag associated with this view and the specified key.
21284     *
21285     * @param key The key identifying the tag
21286     *
21287     * @return the Object stored in this view as a tag, or {@code null} if not
21288     *         set
21289     *
21290     * @see #setTag(int, Object)
21291     * @see #getTag()
21292     */
21293    public Object getTag(int key) {
21294        if (mKeyedTags != null) return mKeyedTags.get(key);
21295        return null;
21296    }
21297
21298    /**
21299     * Sets a tag associated with this view and a key. A tag can be used
21300     * to mark a view in its hierarchy and does not have to be unique within
21301     * the hierarchy. Tags can also be used to store data within a view
21302     * without resorting to another data structure.
21303     *
21304     * The specified key should be an id declared in the resources of the
21305     * application to ensure it is unique (see the <a
21306     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21307     * Keys identified as belonging to
21308     * the Android framework or not associated with any package will cause
21309     * an {@link IllegalArgumentException} to be thrown.
21310     *
21311     * @param key The key identifying the tag
21312     * @param tag An Object to tag the view with
21313     *
21314     * @throws IllegalArgumentException If they specified key is not valid
21315     *
21316     * @see #setTag(Object)
21317     * @see #getTag(int)
21318     */
21319    public void setTag(int key, final Object tag) {
21320        // If the package id is 0x00 or 0x01, it's either an undefined package
21321        // or a framework id
21322        if ((key >>> 24) < 2) {
21323            throw new IllegalArgumentException("The key must be an application-specific "
21324                    + "resource id.");
21325        }
21326
21327        setKeyedTag(key, tag);
21328    }
21329
21330    /**
21331     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21332     * framework id.
21333     *
21334     * @hide
21335     */
21336    public void setTagInternal(int key, Object tag) {
21337        if ((key >>> 24) != 0x1) {
21338            throw new IllegalArgumentException("The key must be a framework-specific "
21339                    + "resource id.");
21340        }
21341
21342        setKeyedTag(key, tag);
21343    }
21344
21345    private void setKeyedTag(int key, Object tag) {
21346        if (mKeyedTags == null) {
21347            mKeyedTags = new SparseArray<Object>(2);
21348        }
21349
21350        mKeyedTags.put(key, tag);
21351    }
21352
21353    /**
21354     * Prints information about this view in the log output, with the tag
21355     * {@link #VIEW_LOG_TAG}.
21356     *
21357     * @hide
21358     */
21359    public void debug() {
21360        debug(0);
21361    }
21362
21363    /**
21364     * Prints information about this view in the log output, with the tag
21365     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21366     * indentation defined by the <code>depth</code>.
21367     *
21368     * @param depth the indentation level
21369     *
21370     * @hide
21371     */
21372    protected void debug(int depth) {
21373        String output = debugIndent(depth - 1);
21374
21375        output += "+ " + this;
21376        int id = getId();
21377        if (id != -1) {
21378            output += " (id=" + id + ")";
21379        }
21380        Object tag = getTag();
21381        if (tag != null) {
21382            output += " (tag=" + tag + ")";
21383        }
21384        Log.d(VIEW_LOG_TAG, output);
21385
21386        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21387            output = debugIndent(depth) + " FOCUSED";
21388            Log.d(VIEW_LOG_TAG, output);
21389        }
21390
21391        output = debugIndent(depth);
21392        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21393                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21394                + "} ";
21395        Log.d(VIEW_LOG_TAG, output);
21396
21397        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21398                || mPaddingBottom != 0) {
21399            output = debugIndent(depth);
21400            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21401                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21402            Log.d(VIEW_LOG_TAG, output);
21403        }
21404
21405        output = debugIndent(depth);
21406        output += "mMeasureWidth=" + mMeasuredWidth +
21407                " mMeasureHeight=" + mMeasuredHeight;
21408        Log.d(VIEW_LOG_TAG, output);
21409
21410        output = debugIndent(depth);
21411        if (mLayoutParams == null) {
21412            output += "BAD! no layout params";
21413        } else {
21414            output = mLayoutParams.debug(output);
21415        }
21416        Log.d(VIEW_LOG_TAG, output);
21417
21418        output = debugIndent(depth);
21419        output += "flags={";
21420        output += View.printFlags(mViewFlags);
21421        output += "}";
21422        Log.d(VIEW_LOG_TAG, output);
21423
21424        output = debugIndent(depth);
21425        output += "privateFlags={";
21426        output += View.printPrivateFlags(mPrivateFlags);
21427        output += "}";
21428        Log.d(VIEW_LOG_TAG, output);
21429    }
21430
21431    /**
21432     * Creates a string of whitespaces used for indentation.
21433     *
21434     * @param depth the indentation level
21435     * @return a String containing (depth * 2 + 3) * 2 white spaces
21436     *
21437     * @hide
21438     */
21439    protected static String debugIndent(int depth) {
21440        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21441        for (int i = 0; i < (depth * 2) + 3; i++) {
21442            spaces.append(' ').append(' ');
21443        }
21444        return spaces.toString();
21445    }
21446
21447    /**
21448     * <p>Return the offset of the widget's text baseline from the widget's top
21449     * boundary. If this widget does not support baseline alignment, this
21450     * method returns -1. </p>
21451     *
21452     * @return the offset of the baseline within the widget's bounds or -1
21453     *         if baseline alignment is not supported
21454     */
21455    @ViewDebug.ExportedProperty(category = "layout")
21456    public int getBaseline() {
21457        return -1;
21458    }
21459
21460    /**
21461     * Returns whether the view hierarchy is currently undergoing a layout pass. This
21462     * information is useful to avoid situations such as calling {@link #requestLayout()} during
21463     * a layout pass.
21464     *
21465     * @return whether the view hierarchy is currently undergoing a layout pass
21466     */
21467    public boolean isInLayout() {
21468        ViewRootImpl viewRoot = getViewRootImpl();
21469        return (viewRoot != null && viewRoot.isInLayout());
21470    }
21471
21472    /**
21473     * Call this when something has changed which has invalidated the
21474     * layout of this view. This will schedule a layout pass of the view
21475     * tree. This should not be called while the view hierarchy is currently in a layout
21476     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21477     * end of the current layout pass (and then layout will run again) or after the current
21478     * frame is drawn and the next layout occurs.
21479     *
21480     * <p>Subclasses which override this method should call the superclass method to
21481     * handle possible request-during-layout errors correctly.</p>
21482     */
21483    @CallSuper
21484    public void requestLayout() {
21485        if (mMeasureCache != null) mMeasureCache.clear();
21486
21487        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21488            // Only trigger request-during-layout logic if this is the view requesting it,
21489            // not the views in its parent hierarchy
21490            ViewRootImpl viewRoot = getViewRootImpl();
21491            if (viewRoot != null && viewRoot.isInLayout()) {
21492                if (!viewRoot.requestLayoutDuringLayout(this)) {
21493                    return;
21494                }
21495            }
21496            mAttachInfo.mViewRequestingLayout = this;
21497        }
21498
21499        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21500        mPrivateFlags |= PFLAG_INVALIDATED;
21501
21502        if (mParent != null && !mParent.isLayoutRequested()) {
21503            mParent.requestLayout();
21504        }
21505        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21506            mAttachInfo.mViewRequestingLayout = null;
21507        }
21508    }
21509
21510    /**
21511     * Forces this view to be laid out during the next layout pass.
21512     * This method does not call requestLayout() or forceLayout()
21513     * on the parent.
21514     */
21515    public void forceLayout() {
21516        if (mMeasureCache != null) mMeasureCache.clear();
21517
21518        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21519        mPrivateFlags |= PFLAG_INVALIDATED;
21520    }
21521
21522    /**
21523     * <p>
21524     * This is called to find out how big a view should be. The parent
21525     * supplies constraint information in the width and height parameters.
21526     * </p>
21527     *
21528     * <p>
21529     * The actual measurement work of a view is performed in
21530     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
21531     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
21532     * </p>
21533     *
21534     *
21535     * @param widthMeasureSpec Horizontal space requirements as imposed by the
21536     *        parent
21537     * @param heightMeasureSpec Vertical space requirements as imposed by the
21538     *        parent
21539     *
21540     * @see #onMeasure(int, int)
21541     */
21542    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
21543        boolean optical = isLayoutModeOptical(this);
21544        if (optical != isLayoutModeOptical(mParent)) {
21545            Insets insets = getOpticalInsets();
21546            int oWidth  = insets.left + insets.right;
21547            int oHeight = insets.top  + insets.bottom;
21548            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
21549            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
21550        }
21551
21552        // Suppress sign extension for the low bytes
21553        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
21554        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
21555
21556        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21557
21558        // Optimize layout by avoiding an extra EXACTLY pass when the view is
21559        // already measured as the correct size. In API 23 and below, this
21560        // extra pass is required to make LinearLayout re-distribute weight.
21561        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
21562                || heightMeasureSpec != mOldHeightMeasureSpec;
21563        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
21564                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
21565        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
21566                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
21567        final boolean needsLayout = specChanged
21568                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
21569
21570        if (forceLayout || needsLayout) {
21571            // first clears the measured dimension flag
21572            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
21573
21574            resolveRtlPropertiesIfNeeded();
21575
21576            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
21577            if (cacheIndex < 0 || sIgnoreMeasureCache) {
21578                // measure ourselves, this should set the measured dimension flag back
21579                onMeasure(widthMeasureSpec, heightMeasureSpec);
21580                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21581            } else {
21582                long value = mMeasureCache.valueAt(cacheIndex);
21583                // Casting a long to int drops the high 32 bits, no mask needed
21584                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
21585                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
21586            }
21587
21588            // flag not set, setMeasuredDimension() was not invoked, we raise
21589            // an exception to warn the developer
21590            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
21591                throw new IllegalStateException("View with id " + getId() + ": "
21592                        + getClass().getName() + "#onMeasure() did not set the"
21593                        + " measured dimension by calling"
21594                        + " setMeasuredDimension()");
21595            }
21596
21597            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
21598        }
21599
21600        mOldWidthMeasureSpec = widthMeasureSpec;
21601        mOldHeightMeasureSpec = heightMeasureSpec;
21602
21603        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
21604                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
21605    }
21606
21607    /**
21608     * <p>
21609     * Measure the view and its content to determine the measured width and the
21610     * measured height. This method is invoked by {@link #measure(int, int)} and
21611     * should be overridden by subclasses to provide accurate and efficient
21612     * measurement of their contents.
21613     * </p>
21614     *
21615     * <p>
21616     * <strong>CONTRACT:</strong> When overriding this method, you
21617     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
21618     * measured width and height of this view. Failure to do so will trigger an
21619     * <code>IllegalStateException</code>, thrown by
21620     * {@link #measure(int, int)}. Calling the superclass'
21621     * {@link #onMeasure(int, int)} is a valid use.
21622     * </p>
21623     *
21624     * <p>
21625     * The base class implementation of measure defaults to the background size,
21626     * unless a larger size is allowed by the MeasureSpec. Subclasses should
21627     * override {@link #onMeasure(int, int)} to provide better measurements of
21628     * their content.
21629     * </p>
21630     *
21631     * <p>
21632     * If this method is overridden, it is the subclass's responsibility to make
21633     * sure the measured height and width are at least the view's minimum height
21634     * and width ({@link #getSuggestedMinimumHeight()} and
21635     * {@link #getSuggestedMinimumWidth()}).
21636     * </p>
21637     *
21638     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
21639     *                         The requirements are encoded with
21640     *                         {@link android.view.View.MeasureSpec}.
21641     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
21642     *                         The requirements are encoded with
21643     *                         {@link android.view.View.MeasureSpec}.
21644     *
21645     * @see #getMeasuredWidth()
21646     * @see #getMeasuredHeight()
21647     * @see #setMeasuredDimension(int, int)
21648     * @see #getSuggestedMinimumHeight()
21649     * @see #getSuggestedMinimumWidth()
21650     * @see android.view.View.MeasureSpec#getMode(int)
21651     * @see android.view.View.MeasureSpec#getSize(int)
21652     */
21653    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
21654        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
21655                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
21656    }
21657
21658    /**
21659     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
21660     * measured width and measured height. Failing to do so will trigger an
21661     * exception at measurement time.</p>
21662     *
21663     * @param measuredWidth The measured width of this view.  May be a complex
21664     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21665     * {@link #MEASURED_STATE_TOO_SMALL}.
21666     * @param measuredHeight The measured height of this view.  May be a complex
21667     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21668     * {@link #MEASURED_STATE_TOO_SMALL}.
21669     */
21670    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
21671        boolean optical = isLayoutModeOptical(this);
21672        if (optical != isLayoutModeOptical(mParent)) {
21673            Insets insets = getOpticalInsets();
21674            int opticalWidth  = insets.left + insets.right;
21675            int opticalHeight = insets.top  + insets.bottom;
21676
21677            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
21678            measuredHeight += optical ? opticalHeight : -opticalHeight;
21679        }
21680        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
21681    }
21682
21683    /**
21684     * Sets the measured dimension without extra processing for things like optical bounds.
21685     * Useful for reapplying consistent values that have already been cooked with adjustments
21686     * for optical bounds, etc. such as those from the measurement cache.
21687     *
21688     * @param measuredWidth The measured width of this view.  May be a complex
21689     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21690     * {@link #MEASURED_STATE_TOO_SMALL}.
21691     * @param measuredHeight The measured height of this view.  May be a complex
21692     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
21693     * {@link #MEASURED_STATE_TOO_SMALL}.
21694     */
21695    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
21696        mMeasuredWidth = measuredWidth;
21697        mMeasuredHeight = measuredHeight;
21698
21699        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
21700    }
21701
21702    /**
21703     * Merge two states as returned by {@link #getMeasuredState()}.
21704     * @param curState The current state as returned from a view or the result
21705     * of combining multiple views.
21706     * @param newState The new view state to combine.
21707     * @return Returns a new integer reflecting the combination of the two
21708     * states.
21709     */
21710    public static int combineMeasuredStates(int curState, int newState) {
21711        return curState | newState;
21712    }
21713
21714    /**
21715     * Version of {@link #resolveSizeAndState(int, int, int)}
21716     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
21717     */
21718    public static int resolveSize(int size, int measureSpec) {
21719        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
21720    }
21721
21722    /**
21723     * Utility to reconcile a desired size and state, with constraints imposed
21724     * by a MeasureSpec. Will take the desired size, unless a different size
21725     * is imposed by the constraints. The returned value is a compound integer,
21726     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
21727     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
21728     * resulting size is smaller than the size the view wants to be.
21729     *
21730     * @param size How big the view wants to be.
21731     * @param measureSpec Constraints imposed by the parent.
21732     * @param childMeasuredState Size information bit mask for the view's
21733     *                           children.
21734     * @return Size information bit mask as defined by
21735     *         {@link #MEASURED_SIZE_MASK} and
21736     *         {@link #MEASURED_STATE_TOO_SMALL}.
21737     */
21738    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
21739        final int specMode = MeasureSpec.getMode(measureSpec);
21740        final int specSize = MeasureSpec.getSize(measureSpec);
21741        final int result;
21742        switch (specMode) {
21743            case MeasureSpec.AT_MOST:
21744                if (specSize < size) {
21745                    result = specSize | MEASURED_STATE_TOO_SMALL;
21746                } else {
21747                    result = size;
21748                }
21749                break;
21750            case MeasureSpec.EXACTLY:
21751                result = specSize;
21752                break;
21753            case MeasureSpec.UNSPECIFIED:
21754            default:
21755                result = size;
21756        }
21757        return result | (childMeasuredState & MEASURED_STATE_MASK);
21758    }
21759
21760    /**
21761     * Utility to return a default size. Uses the supplied size if the
21762     * MeasureSpec imposed no constraints. Will get larger if allowed
21763     * by the MeasureSpec.
21764     *
21765     * @param size Default size for this view
21766     * @param measureSpec Constraints imposed by the parent
21767     * @return The size this view should be.
21768     */
21769    public static int getDefaultSize(int size, int measureSpec) {
21770        int result = size;
21771        int specMode = MeasureSpec.getMode(measureSpec);
21772        int specSize = MeasureSpec.getSize(measureSpec);
21773
21774        switch (specMode) {
21775        case MeasureSpec.UNSPECIFIED:
21776            result = size;
21777            break;
21778        case MeasureSpec.AT_MOST:
21779        case MeasureSpec.EXACTLY:
21780            result = specSize;
21781            break;
21782        }
21783        return result;
21784    }
21785
21786    /**
21787     * Returns the suggested minimum height that the view should use. This
21788     * returns the maximum of the view's minimum height
21789     * and the background's minimum height
21790     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
21791     * <p>
21792     * When being used in {@link #onMeasure(int, int)}, the caller should still
21793     * ensure the returned height is within the requirements of the parent.
21794     *
21795     * @return The suggested minimum height of the view.
21796     */
21797    protected int getSuggestedMinimumHeight() {
21798        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
21799
21800    }
21801
21802    /**
21803     * Returns the suggested minimum width that the view should use. This
21804     * returns the maximum of the view's minimum width
21805     * and the background's minimum width
21806     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
21807     * <p>
21808     * When being used in {@link #onMeasure(int, int)}, the caller should still
21809     * ensure the returned width is within the requirements of the parent.
21810     *
21811     * @return The suggested minimum width of the view.
21812     */
21813    protected int getSuggestedMinimumWidth() {
21814        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
21815    }
21816
21817    /**
21818     * Returns the minimum height of the view.
21819     *
21820     * @return the minimum height the view will try to be, in pixels
21821     *
21822     * @see #setMinimumHeight(int)
21823     *
21824     * @attr ref android.R.styleable#View_minHeight
21825     */
21826    public int getMinimumHeight() {
21827        return mMinHeight;
21828    }
21829
21830    /**
21831     * Sets the minimum height of the view. It is not guaranteed the view will
21832     * be able to achieve this minimum height (for example, if its parent layout
21833     * constrains it with less available height).
21834     *
21835     * @param minHeight The minimum height the view will try to be, in pixels
21836     *
21837     * @see #getMinimumHeight()
21838     *
21839     * @attr ref android.R.styleable#View_minHeight
21840     */
21841    @RemotableViewMethod
21842    public void setMinimumHeight(int minHeight) {
21843        mMinHeight = minHeight;
21844        requestLayout();
21845    }
21846
21847    /**
21848     * Returns the minimum width of the view.
21849     *
21850     * @return the minimum width the view will try to be, in pixels
21851     *
21852     * @see #setMinimumWidth(int)
21853     *
21854     * @attr ref android.R.styleable#View_minWidth
21855     */
21856    public int getMinimumWidth() {
21857        return mMinWidth;
21858    }
21859
21860    /**
21861     * Sets the minimum width of the view. It is not guaranteed the view will
21862     * be able to achieve this minimum width (for example, if its parent layout
21863     * constrains it with less available width).
21864     *
21865     * @param minWidth The minimum width the view will try to be, in pixels
21866     *
21867     * @see #getMinimumWidth()
21868     *
21869     * @attr ref android.R.styleable#View_minWidth
21870     */
21871    public void setMinimumWidth(int minWidth) {
21872        mMinWidth = minWidth;
21873        requestLayout();
21874
21875    }
21876
21877    /**
21878     * Get the animation currently associated with this view.
21879     *
21880     * @return The animation that is currently playing or
21881     *         scheduled to play for this view.
21882     */
21883    public Animation getAnimation() {
21884        return mCurrentAnimation;
21885    }
21886
21887    /**
21888     * Start the specified animation now.
21889     *
21890     * @param animation the animation to start now
21891     */
21892    public void startAnimation(Animation animation) {
21893        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
21894        setAnimation(animation);
21895        invalidateParentCaches();
21896        invalidate(true);
21897    }
21898
21899    /**
21900     * Cancels any animations for this view.
21901     */
21902    public void clearAnimation() {
21903        if (mCurrentAnimation != null) {
21904            mCurrentAnimation.detach();
21905        }
21906        mCurrentAnimation = null;
21907        invalidateParentIfNeeded();
21908    }
21909
21910    /**
21911     * Sets the next animation to play for this view.
21912     * If you want the animation to play immediately, use
21913     * {@link #startAnimation(android.view.animation.Animation)} instead.
21914     * This method provides allows fine-grained
21915     * control over the start time and invalidation, but you
21916     * must make sure that 1) the animation has a start time set, and
21917     * 2) the view's parent (which controls animations on its children)
21918     * will be invalidated when the animation is supposed to
21919     * start.
21920     *
21921     * @param animation The next animation, or null.
21922     */
21923    public void setAnimation(Animation animation) {
21924        mCurrentAnimation = animation;
21925
21926        if (animation != null) {
21927            // If the screen is off assume the animation start time is now instead of
21928            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
21929            // would cause the animation to start when the screen turns back on
21930            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
21931                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
21932                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
21933            }
21934            animation.reset();
21935        }
21936    }
21937
21938    /**
21939     * Invoked by a parent ViewGroup to notify the start of the animation
21940     * currently associated with this view. If you override this method,
21941     * always call super.onAnimationStart();
21942     *
21943     * @see #setAnimation(android.view.animation.Animation)
21944     * @see #getAnimation()
21945     */
21946    @CallSuper
21947    protected void onAnimationStart() {
21948        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
21949    }
21950
21951    /**
21952     * Invoked by a parent ViewGroup to notify the end of the animation
21953     * currently associated with this view. If you override this method,
21954     * always call super.onAnimationEnd();
21955     *
21956     * @see #setAnimation(android.view.animation.Animation)
21957     * @see #getAnimation()
21958     */
21959    @CallSuper
21960    protected void onAnimationEnd() {
21961        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
21962    }
21963
21964    /**
21965     * Invoked if there is a Transform that involves alpha. Subclass that can
21966     * draw themselves with the specified alpha should return true, and then
21967     * respect that alpha when their onDraw() is called. If this returns false
21968     * then the view may be redirected to draw into an offscreen buffer to
21969     * fulfill the request, which will look fine, but may be slower than if the
21970     * subclass handles it internally. The default implementation returns false.
21971     *
21972     * @param alpha The alpha (0..255) to apply to the view's drawing
21973     * @return true if the view can draw with the specified alpha.
21974     */
21975    protected boolean onSetAlpha(int alpha) {
21976        return false;
21977    }
21978
21979    /**
21980     * This is used by the RootView to perform an optimization when
21981     * the view hierarchy contains one or several SurfaceView.
21982     * SurfaceView is always considered transparent, but its children are not,
21983     * therefore all View objects remove themselves from the global transparent
21984     * region (passed as a parameter to this function).
21985     *
21986     * @param region The transparent region for this ViewAncestor (window).
21987     *
21988     * @return Returns true if the effective visibility of the view at this
21989     * point is opaque, regardless of the transparent region; returns false
21990     * if it is possible for underlying windows to be seen behind the view.
21991     *
21992     * {@hide}
21993     */
21994    public boolean gatherTransparentRegion(Region region) {
21995        final AttachInfo attachInfo = mAttachInfo;
21996        if (region != null && attachInfo != null) {
21997            final int pflags = mPrivateFlags;
21998            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
21999                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
22000                // remove it from the transparent region.
22001                final int[] location = attachInfo.mTransparentLocation;
22002                getLocationInWindow(location);
22003                // When a view has Z value, then it will be better to leave some area below the view
22004                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
22005                // the bottom part needs more offset than the left, top and right parts due to the
22006                // spot light effects.
22007                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
22008                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
22009                        location[0] + mRight - mLeft + shadowOffset,
22010                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
22011            } else {
22012                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
22013                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
22014                    // the background drawable's non-transparent parts from this transparent region.
22015                    applyDrawableToTransparentRegion(mBackground, region);
22016                }
22017                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
22018                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
22019                    // Similarly, we remove the foreground drawable's non-transparent parts.
22020                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
22021                }
22022                if (mDefaultFocusHighlight != null
22023                        && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
22024                    // Similarly, we remove the default focus highlight's non-transparent parts.
22025                    applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
22026                }
22027            }
22028        }
22029        return true;
22030    }
22031
22032    /**
22033     * Play a sound effect for this view.
22034     *
22035     * <p>The framework will play sound effects for some built in actions, such as
22036     * clicking, but you may wish to play these effects in your widget,
22037     * for instance, for internal navigation.
22038     *
22039     * <p>The sound effect will only be played if sound effects are enabled by the user, and
22040     * {@link #isSoundEffectsEnabled()} is true.
22041     *
22042     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
22043     */
22044    public void playSoundEffect(int soundConstant) {
22045        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
22046            return;
22047        }
22048        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
22049    }
22050
22051    /**
22052     * BZZZTT!!1!
22053     *
22054     * <p>Provide haptic feedback to the user for this view.
22055     *
22056     * <p>The framework will provide haptic feedback for some built in actions,
22057     * such as long presses, but you may wish to provide feedback for your
22058     * own widget.
22059     *
22060     * <p>The feedback will only be performed if
22061     * {@link #isHapticFeedbackEnabled()} is true.
22062     *
22063     * @param feedbackConstant One of the constants defined in
22064     * {@link HapticFeedbackConstants}
22065     */
22066    public boolean performHapticFeedback(int feedbackConstant) {
22067        return performHapticFeedback(feedbackConstant, 0);
22068    }
22069
22070    /**
22071     * BZZZTT!!1!
22072     *
22073     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
22074     *
22075     * @param feedbackConstant One of the constants defined in
22076     * {@link HapticFeedbackConstants}
22077     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
22078     */
22079    public boolean performHapticFeedback(int feedbackConstant, int flags) {
22080        if (mAttachInfo == null) {
22081            return false;
22082        }
22083        //noinspection SimplifiableIfStatement
22084        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
22085                && !isHapticFeedbackEnabled()) {
22086            return false;
22087        }
22088        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
22089                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
22090    }
22091
22092    /**
22093     * Request that the visibility of the status bar or other screen/window
22094     * decorations be changed.
22095     *
22096     * <p>This method is used to put the over device UI into temporary modes
22097     * where the user's attention is focused more on the application content,
22098     * by dimming or hiding surrounding system affordances.  This is typically
22099     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
22100     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
22101     * to be placed behind the action bar (and with these flags other system
22102     * affordances) so that smooth transitions between hiding and showing them
22103     * can be done.
22104     *
22105     * <p>Two representative examples of the use of system UI visibility is
22106     * implementing a content browsing application (like a magazine reader)
22107     * and a video playing application.
22108     *
22109     * <p>The first code shows a typical implementation of a View in a content
22110     * browsing application.  In this implementation, the application goes
22111     * into a content-oriented mode by hiding the status bar and action bar,
22112     * and putting the navigation elements into lights out mode.  The user can
22113     * then interact with content while in this mode.  Such an application should
22114     * provide an easy way for the user to toggle out of the mode (such as to
22115     * check information in the status bar or access notifications).  In the
22116     * implementation here, this is done simply by tapping on the content.
22117     *
22118     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
22119     *      content}
22120     *
22121     * <p>This second code sample shows a typical implementation of a View
22122     * in a video playing application.  In this situation, while the video is
22123     * playing the application would like to go into a complete full-screen mode,
22124     * to use as much of the display as possible for the video.  When in this state
22125     * the user can not interact with the application; the system intercepts
22126     * touching on the screen to pop the UI out of full screen mode.  See
22127     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
22128     *
22129     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
22130     *      content}
22131     *
22132     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22133     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22134     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22135     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22136     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22137     */
22138    public void setSystemUiVisibility(int visibility) {
22139        if (visibility != mSystemUiVisibility) {
22140            mSystemUiVisibility = visibility;
22141            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22142                mParent.recomputeViewAttributes(this);
22143            }
22144        }
22145    }
22146
22147    /**
22148     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
22149     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22150     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22151     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22152     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22153     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22154     */
22155    public int getSystemUiVisibility() {
22156        return mSystemUiVisibility;
22157    }
22158
22159    /**
22160     * Returns the current system UI visibility that is currently set for
22161     * the entire window.  This is the combination of the
22162     * {@link #setSystemUiVisibility(int)} values supplied by all of the
22163     * views in the window.
22164     */
22165    public int getWindowSystemUiVisibility() {
22166        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
22167    }
22168
22169    /**
22170     * Override to find out when the window's requested system UI visibility
22171     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
22172     * This is different from the callbacks received through
22173     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
22174     * in that this is only telling you about the local request of the window,
22175     * not the actual values applied by the system.
22176     */
22177    public void onWindowSystemUiVisibilityChanged(int visible) {
22178    }
22179
22180    /**
22181     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
22182     * the view hierarchy.
22183     */
22184    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
22185        onWindowSystemUiVisibilityChanged(visible);
22186    }
22187
22188    /**
22189     * Set a listener to receive callbacks when the visibility of the system bar changes.
22190     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
22191     */
22192    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
22193        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
22194        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22195            mParent.recomputeViewAttributes(this);
22196        }
22197    }
22198
22199    /**
22200     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
22201     * the view hierarchy.
22202     */
22203    public void dispatchSystemUiVisibilityChanged(int visibility) {
22204        ListenerInfo li = mListenerInfo;
22205        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
22206            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
22207                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
22208        }
22209    }
22210
22211    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
22212        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
22213        if (val != mSystemUiVisibility) {
22214            setSystemUiVisibility(val);
22215            return true;
22216        }
22217        return false;
22218    }
22219
22220    /** @hide */
22221    public void setDisabledSystemUiVisibility(int flags) {
22222        if (mAttachInfo != null) {
22223            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
22224                mAttachInfo.mDisabledSystemUiVisibility = flags;
22225                if (mParent != null) {
22226                    mParent.recomputeViewAttributes(this);
22227                }
22228            }
22229        }
22230    }
22231
22232    /**
22233     * Creates an image that the system displays during the drag and drop
22234     * operation. This is called a &quot;drag shadow&quot;. The default implementation
22235     * for a DragShadowBuilder based on a View returns an image that has exactly the same
22236     * appearance as the given View. The default also positions the center of the drag shadow
22237     * directly under the touch point. If no View is provided (the constructor with no parameters
22238     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
22239     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
22240     * default is an invisible drag shadow.
22241     * <p>
22242     * You are not required to use the View you provide to the constructor as the basis of the
22243     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
22244     * anything you want as the drag shadow.
22245     * </p>
22246     * <p>
22247     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
22248     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
22249     *  size and position of the drag shadow. It uses this data to construct a
22250     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
22251     *  so that your application can draw the shadow image in the Canvas.
22252     * </p>
22253     *
22254     * <div class="special reference">
22255     * <h3>Developer Guides</h3>
22256     * <p>For a guide to implementing drag and drop features, read the
22257     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22258     * </div>
22259     */
22260    public static class DragShadowBuilder {
22261        private final WeakReference<View> mView;
22262
22263        /**
22264         * Constructs a shadow image builder based on a View. By default, the resulting drag
22265         * shadow will have the same appearance and dimensions as the View, with the touch point
22266         * over the center of the View.
22267         * @param view A View. Any View in scope can be used.
22268         */
22269        public DragShadowBuilder(View view) {
22270            mView = new WeakReference<View>(view);
22271        }
22272
22273        /**
22274         * Construct a shadow builder object with no associated View.  This
22275         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
22276         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
22277         * to supply the drag shadow's dimensions and appearance without
22278         * reference to any View object. If they are not overridden, then the result is an
22279         * invisible drag shadow.
22280         */
22281        public DragShadowBuilder() {
22282            mView = new WeakReference<View>(null);
22283        }
22284
22285        /**
22286         * Returns the View object that had been passed to the
22287         * {@link #View.DragShadowBuilder(View)}
22288         * constructor.  If that View parameter was {@code null} or if the
22289         * {@link #View.DragShadowBuilder()}
22290         * constructor was used to instantiate the builder object, this method will return
22291         * null.
22292         *
22293         * @return The View object associate with this builder object.
22294         */
22295        @SuppressWarnings({"JavadocReference"})
22296        final public View getView() {
22297            return mView.get();
22298        }
22299
22300        /**
22301         * Provides the metrics for the shadow image. These include the dimensions of
22302         * the shadow image, and the point within that shadow that should
22303         * be centered under the touch location while dragging.
22304         * <p>
22305         * The default implementation sets the dimensions of the shadow to be the
22306         * same as the dimensions of the View itself and centers the shadow under
22307         * the touch point.
22308         * </p>
22309         *
22310         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22311         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22312         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22313         * image.
22314         *
22315         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22316         * shadow image that should be underneath the touch point during the drag and drop
22317         * operation. Your application must set {@link android.graphics.Point#x} to the
22318         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22319         */
22320        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22321            final View view = mView.get();
22322            if (view != null) {
22323                outShadowSize.set(view.getWidth(), view.getHeight());
22324                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22325            } else {
22326                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22327            }
22328        }
22329
22330        /**
22331         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22332         * based on the dimensions it received from the
22333         * {@link #onProvideShadowMetrics(Point, Point)} callback.
22334         *
22335         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22336         */
22337        public void onDrawShadow(Canvas canvas) {
22338            final View view = mView.get();
22339            if (view != null) {
22340                view.draw(canvas);
22341            } else {
22342                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22343            }
22344        }
22345    }
22346
22347    /**
22348     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22349     * startDragAndDrop()} for newer platform versions.
22350     */
22351    @Deprecated
22352    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22353                                   Object myLocalState, int flags) {
22354        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22355    }
22356
22357    /**
22358     * Starts a drag and drop operation. When your application calls this method, it passes a
22359     * {@link android.view.View.DragShadowBuilder} object to the system. The
22360     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22361     * to get metrics for the drag shadow, and then calls the object's
22362     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22363     * <p>
22364     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22365     *  drag events to all the View objects in your application that are currently visible. It does
22366     *  this either by calling the View object's drag listener (an implementation of
22367     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22368     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22369     *  Both are passed a {@link android.view.DragEvent} object that has a
22370     *  {@link android.view.DragEvent#getAction()} value of
22371     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22372     * </p>
22373     * <p>
22374     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22375     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22376     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22377     * to the View the user selected for dragging.
22378     * </p>
22379     * @param data A {@link android.content.ClipData} object pointing to the data to be
22380     * transferred by the drag and drop operation.
22381     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22382     * drag shadow.
22383     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22384     * drop operation. When dispatching drag events to views in the same activity this object
22385     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22386     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22387     * will return null).
22388     * <p>
22389     * myLocalState is a lightweight mechanism for the sending information from the dragged View
22390     * to the target Views. For example, it can contain flags that differentiate between a
22391     * a copy operation and a move operation.
22392     * </p>
22393     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22394     * flags, or any combination of the following:
22395     *     <ul>
22396     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22397     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22398     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22399     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22400     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22401     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22402     *     </ul>
22403     * @return {@code true} if the method completes successfully, or
22404     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22405     * do a drag, and so no drag operation is in progress.
22406     */
22407    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22408            Object myLocalState, int flags) {
22409        if (ViewDebug.DEBUG_DRAG) {
22410            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22411        }
22412        if (mAttachInfo == null) {
22413            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22414            return false;
22415        }
22416
22417        if (data != null) {
22418            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22419        }
22420
22421        boolean okay = false;
22422
22423        Point shadowSize = new Point();
22424        Point shadowTouchPoint = new Point();
22425        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22426
22427        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22428                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22429            throw new IllegalStateException("Drag shadow dimensions must not be negative");
22430        }
22431
22432        if (ViewDebug.DEBUG_DRAG) {
22433            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22434                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22435        }
22436        if (mAttachInfo.mDragSurface != null) {
22437            mAttachInfo.mDragSurface.release();
22438        }
22439        mAttachInfo.mDragSurface = new Surface();
22440        try {
22441            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22442                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22443            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22444                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22445            if (mAttachInfo.mDragToken != null) {
22446                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22447                try {
22448                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22449                    shadowBuilder.onDrawShadow(canvas);
22450                } finally {
22451                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22452                }
22453
22454                final ViewRootImpl root = getViewRootImpl();
22455
22456                // Cache the local state object for delivery with DragEvents
22457                root.setLocalDragState(myLocalState);
22458
22459                // repurpose 'shadowSize' for the last touch point
22460                root.getLastTouchPoint(shadowSize);
22461
22462                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22463                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22464                        shadowTouchPoint.x, shadowTouchPoint.y, data);
22465                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22466            }
22467        } catch (Exception e) {
22468            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22469            mAttachInfo.mDragSurface.destroy();
22470            mAttachInfo.mDragSurface = null;
22471        }
22472
22473        return okay;
22474    }
22475
22476    /**
22477     * Cancels an ongoing drag and drop operation.
22478     * <p>
22479     * A {@link android.view.DragEvent} object with
22480     * {@link android.view.DragEvent#getAction()} value of
22481     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22482     * {@link android.view.DragEvent#getResult()} value of {@code false}
22483     * will be sent to every
22484     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22485     * even if they are not currently visible.
22486     * </p>
22487     * <p>
22488     * This method can be called on any View in the same window as the View on which
22489     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22490     * was called.
22491     * </p>
22492     */
22493    public final void cancelDragAndDrop() {
22494        if (ViewDebug.DEBUG_DRAG) {
22495            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22496        }
22497        if (mAttachInfo == null) {
22498            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22499            return;
22500        }
22501        if (mAttachInfo.mDragToken != null) {
22502            try {
22503                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22504            } catch (Exception e) {
22505                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22506            }
22507            mAttachInfo.mDragToken = null;
22508        } else {
22509            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
22510        }
22511    }
22512
22513    /**
22514     * Updates the drag shadow for the ongoing drag and drop operation.
22515     *
22516     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22517     * new drag shadow.
22518     */
22519    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
22520        if (ViewDebug.DEBUG_DRAG) {
22521            Log.d(VIEW_LOG_TAG, "updateDragShadow");
22522        }
22523        if (mAttachInfo == null) {
22524            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
22525            return;
22526        }
22527        if (mAttachInfo.mDragToken != null) {
22528            try {
22529                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22530                try {
22531                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22532                    shadowBuilder.onDrawShadow(canvas);
22533                } finally {
22534                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22535                }
22536            } catch (Exception e) {
22537                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
22538            }
22539        } else {
22540            Log.e(VIEW_LOG_TAG, "No active drag");
22541        }
22542    }
22543
22544    /**
22545     * Starts a move from {startX, startY}, the amount of the movement will be the offset
22546     * between {startX, startY} and the new cursor positon.
22547     * @param startX horizontal coordinate where the move started.
22548     * @param startY vertical coordinate where the move started.
22549     * @return whether moving was started successfully.
22550     * @hide
22551     */
22552    public final boolean startMovingTask(float startX, float startY) {
22553        if (ViewDebug.DEBUG_POSITIONING) {
22554            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
22555        }
22556        try {
22557            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
22558        } catch (RemoteException e) {
22559            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
22560        }
22561        return false;
22562    }
22563
22564    /**
22565     * Handles drag events sent by the system following a call to
22566     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
22567     * startDragAndDrop()}.
22568     *<p>
22569     * When the system calls this method, it passes a
22570     * {@link android.view.DragEvent} object. A call to
22571     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
22572     * in DragEvent. The method uses these to determine what is happening in the drag and drop
22573     * operation.
22574     * @param event The {@link android.view.DragEvent} sent by the system.
22575     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
22576     * in DragEvent, indicating the type of drag event represented by this object.
22577     * @return {@code true} if the method was successful, otherwise {@code false}.
22578     * <p>
22579     *  The method should return {@code true} in response to an action type of
22580     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
22581     *  operation.
22582     * </p>
22583     * <p>
22584     *  The method should also return {@code true} in response to an action type of
22585     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
22586     *  {@code false} if it didn't.
22587     * </p>
22588     * <p>
22589     *  For all other events, the return value is ignored.
22590     * </p>
22591     */
22592    public boolean onDragEvent(DragEvent event) {
22593        return false;
22594    }
22595
22596    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
22597    boolean dispatchDragEnterExitInPreN(DragEvent event) {
22598        return callDragEventHandler(event);
22599    }
22600
22601    /**
22602     * Detects if this View is enabled and has a drag event listener.
22603     * If both are true, then it calls the drag event listener with the
22604     * {@link android.view.DragEvent} it received. If the drag event listener returns
22605     * {@code true}, then dispatchDragEvent() returns {@code true}.
22606     * <p>
22607     * For all other cases, the method calls the
22608     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
22609     * method and returns its result.
22610     * </p>
22611     * <p>
22612     * This ensures that a drag event is always consumed, even if the View does not have a drag
22613     * event listener. However, if the View has a listener and the listener returns true, then
22614     * onDragEvent() is not called.
22615     * </p>
22616     */
22617    public boolean dispatchDragEvent(DragEvent event) {
22618        event.mEventHandlerWasCalled = true;
22619        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
22620            event.mAction == DragEvent.ACTION_DROP) {
22621            // About to deliver an event with coordinates to this view. Notify that now this view
22622            // has drag focus. This will send exit/enter events as needed.
22623            getViewRootImpl().setDragFocus(this, event);
22624        }
22625        return callDragEventHandler(event);
22626    }
22627
22628    final boolean callDragEventHandler(DragEvent event) {
22629        final boolean result;
22630
22631        ListenerInfo li = mListenerInfo;
22632        //noinspection SimplifiableIfStatement
22633        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
22634                && li.mOnDragListener.onDrag(this, event)) {
22635            result = true;
22636        } else {
22637            result = onDragEvent(event);
22638        }
22639
22640        switch (event.mAction) {
22641            case DragEvent.ACTION_DRAG_ENTERED: {
22642                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
22643                refreshDrawableState();
22644            } break;
22645            case DragEvent.ACTION_DRAG_EXITED: {
22646                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
22647                refreshDrawableState();
22648            } break;
22649            case DragEvent.ACTION_DRAG_ENDED: {
22650                mPrivateFlags2 &= ~View.DRAG_MASK;
22651                refreshDrawableState();
22652            } break;
22653        }
22654
22655        return result;
22656    }
22657
22658    boolean canAcceptDrag() {
22659        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
22660    }
22661
22662    /**
22663     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
22664     * it is ever exposed at all.
22665     * @hide
22666     */
22667    public void onCloseSystemDialogs(String reason) {
22668    }
22669
22670    /**
22671     * Given a Drawable whose bounds have been set to draw into this view,
22672     * update a Region being computed for
22673     * {@link #gatherTransparentRegion(android.graphics.Region)} so
22674     * that any non-transparent parts of the Drawable are removed from the
22675     * given transparent region.
22676     *
22677     * @param dr The Drawable whose transparency is to be applied to the region.
22678     * @param region A Region holding the current transparency information,
22679     * where any parts of the region that are set are considered to be
22680     * transparent.  On return, this region will be modified to have the
22681     * transparency information reduced by the corresponding parts of the
22682     * Drawable that are not transparent.
22683     * {@hide}
22684     */
22685    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
22686        if (DBG) {
22687            Log.i("View", "Getting transparent region for: " + this);
22688        }
22689        final Region r = dr.getTransparentRegion();
22690        final Rect db = dr.getBounds();
22691        final AttachInfo attachInfo = mAttachInfo;
22692        if (r != null && attachInfo != null) {
22693            final int w = getRight()-getLeft();
22694            final int h = getBottom()-getTop();
22695            if (db.left > 0) {
22696                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
22697                r.op(0, 0, db.left, h, Region.Op.UNION);
22698            }
22699            if (db.right < w) {
22700                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
22701                r.op(db.right, 0, w, h, Region.Op.UNION);
22702            }
22703            if (db.top > 0) {
22704                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
22705                r.op(0, 0, w, db.top, Region.Op.UNION);
22706            }
22707            if (db.bottom < h) {
22708                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
22709                r.op(0, db.bottom, w, h, Region.Op.UNION);
22710            }
22711            final int[] location = attachInfo.mTransparentLocation;
22712            getLocationInWindow(location);
22713            r.translate(location[0], location[1]);
22714            region.op(r, Region.Op.INTERSECT);
22715        } else {
22716            region.op(db, Region.Op.DIFFERENCE);
22717        }
22718    }
22719
22720    private void checkForLongClick(int delayOffset, float x, float y) {
22721        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
22722            mHasPerformedLongPress = false;
22723
22724            if (mPendingCheckForLongPress == null) {
22725                mPendingCheckForLongPress = new CheckForLongPress();
22726            }
22727            mPendingCheckForLongPress.setAnchor(x, y);
22728            mPendingCheckForLongPress.rememberWindowAttachCount();
22729            mPendingCheckForLongPress.rememberPressedState();
22730            postDelayed(mPendingCheckForLongPress,
22731                    ViewConfiguration.getLongPressTimeout() - delayOffset);
22732        }
22733    }
22734
22735    /**
22736     * Inflate a view from an XML resource.  This convenience method wraps the {@link
22737     * LayoutInflater} class, which provides a full range of options for view inflation.
22738     *
22739     * @param context The Context object for your activity or application.
22740     * @param resource The resource ID to inflate
22741     * @param root A view group that will be the parent.  Used to properly inflate the
22742     * layout_* parameters.
22743     * @see LayoutInflater
22744     */
22745    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
22746        LayoutInflater factory = LayoutInflater.from(context);
22747        return factory.inflate(resource, root);
22748    }
22749
22750    /**
22751     * Scroll the view with standard behavior for scrolling beyond the normal
22752     * content boundaries. Views that call this method should override
22753     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
22754     * results of an over-scroll operation.
22755     *
22756     * Views can use this method to handle any touch or fling-based scrolling.
22757     *
22758     * @param deltaX Change in X in pixels
22759     * @param deltaY Change in Y in pixels
22760     * @param scrollX Current X scroll value in pixels before applying deltaX
22761     * @param scrollY Current Y scroll value in pixels before applying deltaY
22762     * @param scrollRangeX Maximum content scroll range along the X axis
22763     * @param scrollRangeY Maximum content scroll range along the Y axis
22764     * @param maxOverScrollX Number of pixels to overscroll by in either direction
22765     *          along the X axis.
22766     * @param maxOverScrollY Number of pixels to overscroll by in either direction
22767     *          along the Y axis.
22768     * @param isTouchEvent true if this scroll operation is the result of a touch event.
22769     * @return true if scrolling was clamped to an over-scroll boundary along either
22770     *          axis, false otherwise.
22771     */
22772    @SuppressWarnings({"UnusedParameters"})
22773    protected boolean overScrollBy(int deltaX, int deltaY,
22774            int scrollX, int scrollY,
22775            int scrollRangeX, int scrollRangeY,
22776            int maxOverScrollX, int maxOverScrollY,
22777            boolean isTouchEvent) {
22778        final int overScrollMode = mOverScrollMode;
22779        final boolean canScrollHorizontal =
22780                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
22781        final boolean canScrollVertical =
22782                computeVerticalScrollRange() > computeVerticalScrollExtent();
22783        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
22784                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
22785        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
22786                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
22787
22788        int newScrollX = scrollX + deltaX;
22789        if (!overScrollHorizontal) {
22790            maxOverScrollX = 0;
22791        }
22792
22793        int newScrollY = scrollY + deltaY;
22794        if (!overScrollVertical) {
22795            maxOverScrollY = 0;
22796        }
22797
22798        // Clamp values if at the limits and record
22799        final int left = -maxOverScrollX;
22800        final int right = maxOverScrollX + scrollRangeX;
22801        final int top = -maxOverScrollY;
22802        final int bottom = maxOverScrollY + scrollRangeY;
22803
22804        boolean clampedX = false;
22805        if (newScrollX > right) {
22806            newScrollX = right;
22807            clampedX = true;
22808        } else if (newScrollX < left) {
22809            newScrollX = left;
22810            clampedX = true;
22811        }
22812
22813        boolean clampedY = false;
22814        if (newScrollY > bottom) {
22815            newScrollY = bottom;
22816            clampedY = true;
22817        } else if (newScrollY < top) {
22818            newScrollY = top;
22819            clampedY = true;
22820        }
22821
22822        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
22823
22824        return clampedX || clampedY;
22825    }
22826
22827    /**
22828     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
22829     * respond to the results of an over-scroll operation.
22830     *
22831     * @param scrollX New X scroll value in pixels
22832     * @param scrollY New Y scroll value in pixels
22833     * @param clampedX True if scrollX was clamped to an over-scroll boundary
22834     * @param clampedY True if scrollY was clamped to an over-scroll boundary
22835     */
22836    protected void onOverScrolled(int scrollX, int scrollY,
22837            boolean clampedX, boolean clampedY) {
22838        // Intentionally empty.
22839    }
22840
22841    /**
22842     * Returns the over-scroll mode for this view. The result will be
22843     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22844     * (allow over-scrolling only if the view content is larger than the container),
22845     * or {@link #OVER_SCROLL_NEVER}.
22846     *
22847     * @return This view's over-scroll mode.
22848     */
22849    public int getOverScrollMode() {
22850        return mOverScrollMode;
22851    }
22852
22853    /**
22854     * Set the over-scroll mode for this view. Valid over-scroll modes are
22855     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
22856     * (allow over-scrolling only if the view content is larger than the container),
22857     * or {@link #OVER_SCROLL_NEVER}.
22858     *
22859     * Setting the over-scroll mode of a view will have an effect only if the
22860     * view is capable of scrolling.
22861     *
22862     * @param overScrollMode The new over-scroll mode for this view.
22863     */
22864    public void setOverScrollMode(int overScrollMode) {
22865        if (overScrollMode != OVER_SCROLL_ALWAYS &&
22866                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
22867                overScrollMode != OVER_SCROLL_NEVER) {
22868            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
22869        }
22870        mOverScrollMode = overScrollMode;
22871    }
22872
22873    /**
22874     * Enable or disable nested scrolling for this view.
22875     *
22876     * <p>If this property is set to true the view will be permitted to initiate nested
22877     * scrolling operations with a compatible parent view in the current hierarchy. If this
22878     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
22879     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
22880     * the nested scroll.</p>
22881     *
22882     * @param enabled true to enable nested scrolling, false to disable
22883     *
22884     * @see #isNestedScrollingEnabled()
22885     */
22886    public void setNestedScrollingEnabled(boolean enabled) {
22887        if (enabled) {
22888            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
22889        } else {
22890            stopNestedScroll();
22891            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
22892        }
22893    }
22894
22895    /**
22896     * Returns true if nested scrolling is enabled for this view.
22897     *
22898     * <p>If nested scrolling is enabled and this View class implementation supports it,
22899     * this view will act as a nested scrolling child view when applicable, forwarding data
22900     * about the scroll operation in progress to a compatible and cooperating nested scrolling
22901     * parent.</p>
22902     *
22903     * @return true if nested scrolling is enabled
22904     *
22905     * @see #setNestedScrollingEnabled(boolean)
22906     */
22907    public boolean isNestedScrollingEnabled() {
22908        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
22909                PFLAG3_NESTED_SCROLLING_ENABLED;
22910    }
22911
22912    /**
22913     * Begin a nestable scroll operation along the given axes.
22914     *
22915     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
22916     *
22917     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
22918     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
22919     * In the case of touch scrolling the nested scroll will be terminated automatically in
22920     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
22921     * In the event of programmatic scrolling the caller must explicitly call
22922     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
22923     *
22924     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
22925     * If it returns false the caller may ignore the rest of this contract until the next scroll.
22926     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
22927     *
22928     * <p>At each incremental step of the scroll the caller should invoke
22929     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
22930     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
22931     * parent at least partially consumed the scroll and the caller should adjust the amount it
22932     * scrolls by.</p>
22933     *
22934     * <p>After applying the remainder of the scroll delta the caller should invoke
22935     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
22936     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
22937     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
22938     * </p>
22939     *
22940     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
22941     *             {@link #SCROLL_AXIS_VERTICAL}.
22942     * @return true if a cooperative parent was found and nested scrolling has been enabled for
22943     *         the current gesture.
22944     *
22945     * @see #stopNestedScroll()
22946     * @see #dispatchNestedPreScroll(int, int, int[], int[])
22947     * @see #dispatchNestedScroll(int, int, int, int, int[])
22948     */
22949    public boolean startNestedScroll(int axes) {
22950        if (hasNestedScrollingParent()) {
22951            // Already in progress
22952            return true;
22953        }
22954        if (isNestedScrollingEnabled()) {
22955            ViewParent p = getParent();
22956            View child = this;
22957            while (p != null) {
22958                try {
22959                    if (p.onStartNestedScroll(child, this, axes)) {
22960                        mNestedScrollingParent = p;
22961                        p.onNestedScrollAccepted(child, this, axes);
22962                        return true;
22963                    }
22964                } catch (AbstractMethodError e) {
22965                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
22966                            "method onStartNestedScroll", e);
22967                    // Allow the search upward to continue
22968                }
22969                if (p instanceof View) {
22970                    child = (View) p;
22971                }
22972                p = p.getParent();
22973            }
22974        }
22975        return false;
22976    }
22977
22978    /**
22979     * Stop a nested scroll in progress.
22980     *
22981     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
22982     *
22983     * @see #startNestedScroll(int)
22984     */
22985    public void stopNestedScroll() {
22986        if (mNestedScrollingParent != null) {
22987            mNestedScrollingParent.onStopNestedScroll(this);
22988            mNestedScrollingParent = null;
22989        }
22990    }
22991
22992    /**
22993     * Returns true if this view has a nested scrolling parent.
22994     *
22995     * <p>The presence of a nested scrolling parent indicates that this view has initiated
22996     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
22997     *
22998     * @return whether this view has a nested scrolling parent
22999     */
23000    public boolean hasNestedScrollingParent() {
23001        return mNestedScrollingParent != null;
23002    }
23003
23004    /**
23005     * Dispatch one step of a nested scroll in progress.
23006     *
23007     * <p>Implementations of views that support nested scrolling should call this to report
23008     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
23009     * is not currently in progress or nested scrolling is not
23010     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
23011     *
23012     * <p>Compatible View implementations should also call
23013     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
23014     * consuming a component of the scroll event themselves.</p>
23015     *
23016     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
23017     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
23018     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
23019     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
23020     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23021     *                       in local view coordinates of this view from before this operation
23022     *                       to after it completes. View implementations may use this to adjust
23023     *                       expected input coordinate tracking.
23024     * @return true if the event was dispatched, false if it could not be dispatched.
23025     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23026     */
23027    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
23028            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
23029        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23030            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
23031                int startX = 0;
23032                int startY = 0;
23033                if (offsetInWindow != null) {
23034                    getLocationInWindow(offsetInWindow);
23035                    startX = offsetInWindow[0];
23036                    startY = offsetInWindow[1];
23037                }
23038
23039                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
23040                        dxUnconsumed, dyUnconsumed);
23041
23042                if (offsetInWindow != null) {
23043                    getLocationInWindow(offsetInWindow);
23044                    offsetInWindow[0] -= startX;
23045                    offsetInWindow[1] -= startY;
23046                }
23047                return true;
23048            } else if (offsetInWindow != null) {
23049                // No motion, no dispatch. Keep offsetInWindow up to date.
23050                offsetInWindow[0] = 0;
23051                offsetInWindow[1] = 0;
23052            }
23053        }
23054        return false;
23055    }
23056
23057    /**
23058     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
23059     *
23060     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
23061     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
23062     * scrolling operation to consume some or all of the scroll operation before the child view
23063     * consumes it.</p>
23064     *
23065     * @param dx Horizontal scroll distance in pixels
23066     * @param dy Vertical scroll distance in pixels
23067     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
23068     *                 and consumed[1] the consumed dy.
23069     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23070     *                       in local view coordinates of this view from before this operation
23071     *                       to after it completes. View implementations may use this to adjust
23072     *                       expected input coordinate tracking.
23073     * @return true if the parent consumed some or all of the scroll delta
23074     * @see #dispatchNestedScroll(int, int, int, int, int[])
23075     */
23076    public boolean dispatchNestedPreScroll(int dx, int dy,
23077            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
23078        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23079            if (dx != 0 || dy != 0) {
23080                int startX = 0;
23081                int startY = 0;
23082                if (offsetInWindow != null) {
23083                    getLocationInWindow(offsetInWindow);
23084                    startX = offsetInWindow[0];
23085                    startY = offsetInWindow[1];
23086                }
23087
23088                if (consumed == null) {
23089                    if (mTempNestedScrollConsumed == null) {
23090                        mTempNestedScrollConsumed = new int[2];
23091                    }
23092                    consumed = mTempNestedScrollConsumed;
23093                }
23094                consumed[0] = 0;
23095                consumed[1] = 0;
23096                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
23097
23098                if (offsetInWindow != null) {
23099                    getLocationInWindow(offsetInWindow);
23100                    offsetInWindow[0] -= startX;
23101                    offsetInWindow[1] -= startY;
23102                }
23103                return consumed[0] != 0 || consumed[1] != 0;
23104            } else if (offsetInWindow != null) {
23105                offsetInWindow[0] = 0;
23106                offsetInWindow[1] = 0;
23107            }
23108        }
23109        return false;
23110    }
23111
23112    /**
23113     * Dispatch a fling to a nested scrolling parent.
23114     *
23115     * <p>This method should be used to indicate that a nested scrolling child has detected
23116     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
23117     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
23118     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
23119     * along a scrollable axis.</p>
23120     *
23121     * <p>If a nested scrolling child view would normally fling but it is at the edge of
23122     * its own content, it can use this method to delegate the fling to its nested scrolling
23123     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
23124     *
23125     * @param velocityX Horizontal fling velocity in pixels per second
23126     * @param velocityY Vertical fling velocity in pixels per second
23127     * @param consumed true if the child consumed the fling, false otherwise
23128     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
23129     */
23130    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
23131        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23132            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
23133        }
23134        return false;
23135    }
23136
23137    /**
23138     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
23139     *
23140     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
23141     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
23142     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
23143     * before the child view consumes it. If this method returns <code>true</code>, a nested
23144     * parent view consumed the fling and this view should not scroll as a result.</p>
23145     *
23146     * <p>For a better user experience, only one view in a nested scrolling chain should consume
23147     * the fling at a time. If a parent view consumed the fling this method will return false.
23148     * Custom view implementations should account for this in two ways:</p>
23149     *
23150     * <ul>
23151     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
23152     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
23153     *     position regardless.</li>
23154     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
23155     *     even to settle back to a valid idle position.</li>
23156     * </ul>
23157     *
23158     * <p>Views should also not offer fling velocities to nested parent views along an axis
23159     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
23160     * should not offer a horizontal fling velocity to its parents since scrolling along that
23161     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
23162     *
23163     * @param velocityX Horizontal fling velocity in pixels per second
23164     * @param velocityY Vertical fling velocity in pixels per second
23165     * @return true if a nested scrolling parent consumed the fling
23166     */
23167    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
23168        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23169            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
23170        }
23171        return false;
23172    }
23173
23174    /**
23175     * Gets a scale factor that determines the distance the view should scroll
23176     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
23177     * @return The vertical scroll scale factor.
23178     * @hide
23179     */
23180    protected float getVerticalScrollFactor() {
23181        if (mVerticalScrollFactor == 0) {
23182            TypedValue outValue = new TypedValue();
23183            if (!mContext.getTheme().resolveAttribute(
23184                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
23185                throw new IllegalStateException(
23186                        "Expected theme to define listPreferredItemHeight.");
23187            }
23188            mVerticalScrollFactor = outValue.getDimension(
23189                    mContext.getResources().getDisplayMetrics());
23190        }
23191        return mVerticalScrollFactor;
23192    }
23193
23194    /**
23195     * Gets a scale factor that determines the distance the view should scroll
23196     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
23197     * @return The horizontal scroll scale factor.
23198     * @hide
23199     */
23200    protected float getHorizontalScrollFactor() {
23201        // TODO: Should use something else.
23202        return getVerticalScrollFactor();
23203    }
23204
23205    /**
23206     * Return the value specifying the text direction or policy that was set with
23207     * {@link #setTextDirection(int)}.
23208     *
23209     * @return the defined text direction. It can be one of:
23210     *
23211     * {@link #TEXT_DIRECTION_INHERIT},
23212     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23213     * {@link #TEXT_DIRECTION_ANY_RTL},
23214     * {@link #TEXT_DIRECTION_LTR},
23215     * {@link #TEXT_DIRECTION_RTL},
23216     * {@link #TEXT_DIRECTION_LOCALE},
23217     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23218     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23219     *
23220     * @attr ref android.R.styleable#View_textDirection
23221     *
23222     * @hide
23223     */
23224    @ViewDebug.ExportedProperty(category = "text", mapping = {
23225            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23226            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23227            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23228            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23229            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23230            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23231            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23232            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23233    })
23234    public int getRawTextDirection() {
23235        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
23236    }
23237
23238    /**
23239     * Set the text direction.
23240     *
23241     * @param textDirection the direction to set. Should be one of:
23242     *
23243     * {@link #TEXT_DIRECTION_INHERIT},
23244     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23245     * {@link #TEXT_DIRECTION_ANY_RTL},
23246     * {@link #TEXT_DIRECTION_LTR},
23247     * {@link #TEXT_DIRECTION_RTL},
23248     * {@link #TEXT_DIRECTION_LOCALE}
23249     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23250     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
23251     *
23252     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
23253     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
23254     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
23255     *
23256     * @attr ref android.R.styleable#View_textDirection
23257     */
23258    public void setTextDirection(int textDirection) {
23259        if (getRawTextDirection() != textDirection) {
23260            // Reset the current text direction and the resolved one
23261            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
23262            resetResolvedTextDirection();
23263            // Set the new text direction
23264            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
23265            // Do resolution
23266            resolveTextDirection();
23267            // Notify change
23268            onRtlPropertiesChanged(getLayoutDirection());
23269            // Refresh
23270            requestLayout();
23271            invalidate(true);
23272        }
23273    }
23274
23275    /**
23276     * Return the resolved text direction.
23277     *
23278     * @return the resolved text direction. Returns one of:
23279     *
23280     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23281     * {@link #TEXT_DIRECTION_ANY_RTL},
23282     * {@link #TEXT_DIRECTION_LTR},
23283     * {@link #TEXT_DIRECTION_RTL},
23284     * {@link #TEXT_DIRECTION_LOCALE},
23285     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23286     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23287     *
23288     * @attr ref android.R.styleable#View_textDirection
23289     */
23290    @ViewDebug.ExportedProperty(category = "text", mapping = {
23291            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23292            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23293            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23294            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23295            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23296            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23297            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23298            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23299    })
23300    public int getTextDirection() {
23301        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23302    }
23303
23304    /**
23305     * Resolve the text direction.
23306     *
23307     * @return true if resolution has been done, false otherwise.
23308     *
23309     * @hide
23310     */
23311    public boolean resolveTextDirection() {
23312        // Reset any previous text direction resolution
23313        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23314
23315        if (hasRtlSupport()) {
23316            // Set resolved text direction flag depending on text direction flag
23317            final int textDirection = getRawTextDirection();
23318            switch(textDirection) {
23319                case TEXT_DIRECTION_INHERIT:
23320                    if (!canResolveTextDirection()) {
23321                        // We cannot do the resolution if there is no parent, so use the default one
23322                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23323                        // Resolution will need to happen again later
23324                        return false;
23325                    }
23326
23327                    // Parent has not yet resolved, so we still return the default
23328                    try {
23329                        if (!mParent.isTextDirectionResolved()) {
23330                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23331                            // Resolution will need to happen again later
23332                            return false;
23333                        }
23334                    } catch (AbstractMethodError e) {
23335                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23336                                " does not fully implement ViewParent", e);
23337                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23338                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23339                        return true;
23340                    }
23341
23342                    // Set current resolved direction to the same value as the parent's one
23343                    int parentResolvedDirection;
23344                    try {
23345                        parentResolvedDirection = mParent.getTextDirection();
23346                    } catch (AbstractMethodError e) {
23347                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23348                                " does not fully implement ViewParent", e);
23349                        parentResolvedDirection = TEXT_DIRECTION_LTR;
23350                    }
23351                    switch (parentResolvedDirection) {
23352                        case TEXT_DIRECTION_FIRST_STRONG:
23353                        case TEXT_DIRECTION_ANY_RTL:
23354                        case TEXT_DIRECTION_LTR:
23355                        case TEXT_DIRECTION_RTL:
23356                        case TEXT_DIRECTION_LOCALE:
23357                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
23358                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
23359                            mPrivateFlags2 |=
23360                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23361                            break;
23362                        default:
23363                            // Default resolved direction is "first strong" heuristic
23364                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23365                    }
23366                    break;
23367                case TEXT_DIRECTION_FIRST_STRONG:
23368                case TEXT_DIRECTION_ANY_RTL:
23369                case TEXT_DIRECTION_LTR:
23370                case TEXT_DIRECTION_RTL:
23371                case TEXT_DIRECTION_LOCALE:
23372                case TEXT_DIRECTION_FIRST_STRONG_LTR:
23373                case TEXT_DIRECTION_FIRST_STRONG_RTL:
23374                    // Resolved direction is the same as text direction
23375                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23376                    break;
23377                default:
23378                    // Default resolved direction is "first strong" heuristic
23379                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23380            }
23381        } else {
23382            // Default resolved direction is "first strong" heuristic
23383            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23384        }
23385
23386        // Set to resolved
23387        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23388        return true;
23389    }
23390
23391    /**
23392     * Check if text direction resolution can be done.
23393     *
23394     * @return true if text direction resolution can be done otherwise return false.
23395     */
23396    public boolean canResolveTextDirection() {
23397        switch (getRawTextDirection()) {
23398            case TEXT_DIRECTION_INHERIT:
23399                if (mParent != null) {
23400                    try {
23401                        return mParent.canResolveTextDirection();
23402                    } catch (AbstractMethodError e) {
23403                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23404                                " does not fully implement ViewParent", e);
23405                    }
23406                }
23407                return false;
23408
23409            default:
23410                return true;
23411        }
23412    }
23413
23414    /**
23415     * Reset resolved text direction. Text direction will be resolved during a call to
23416     * {@link #onMeasure(int, int)}.
23417     *
23418     * @hide
23419     */
23420    public void resetResolvedTextDirection() {
23421        // Reset any previous text direction resolution
23422        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23423        // Set to default value
23424        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23425    }
23426
23427    /**
23428     * @return true if text direction is inherited.
23429     *
23430     * @hide
23431     */
23432    public boolean isTextDirectionInherited() {
23433        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23434    }
23435
23436    /**
23437     * @return true if text direction is resolved.
23438     */
23439    public boolean isTextDirectionResolved() {
23440        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23441    }
23442
23443    /**
23444     * Return the value specifying the text alignment or policy that was set with
23445     * {@link #setTextAlignment(int)}.
23446     *
23447     * @return the defined text alignment. It can be one of:
23448     *
23449     * {@link #TEXT_ALIGNMENT_INHERIT},
23450     * {@link #TEXT_ALIGNMENT_GRAVITY},
23451     * {@link #TEXT_ALIGNMENT_CENTER},
23452     * {@link #TEXT_ALIGNMENT_TEXT_START},
23453     * {@link #TEXT_ALIGNMENT_TEXT_END},
23454     * {@link #TEXT_ALIGNMENT_VIEW_START},
23455     * {@link #TEXT_ALIGNMENT_VIEW_END}
23456     *
23457     * @attr ref android.R.styleable#View_textAlignment
23458     *
23459     * @hide
23460     */
23461    @ViewDebug.ExportedProperty(category = "text", mapping = {
23462            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23463            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23464            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23465            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23466            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23467            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23468            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23469    })
23470    @TextAlignment
23471    public int getRawTextAlignment() {
23472        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23473    }
23474
23475    /**
23476     * Set the text alignment.
23477     *
23478     * @param textAlignment The text alignment to set. Should be one of
23479     *
23480     * {@link #TEXT_ALIGNMENT_INHERIT},
23481     * {@link #TEXT_ALIGNMENT_GRAVITY},
23482     * {@link #TEXT_ALIGNMENT_CENTER},
23483     * {@link #TEXT_ALIGNMENT_TEXT_START},
23484     * {@link #TEXT_ALIGNMENT_TEXT_END},
23485     * {@link #TEXT_ALIGNMENT_VIEW_START},
23486     * {@link #TEXT_ALIGNMENT_VIEW_END}
23487     *
23488     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23489     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23490     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23491     *
23492     * @attr ref android.R.styleable#View_textAlignment
23493     */
23494    public void setTextAlignment(@TextAlignment int textAlignment) {
23495        if (textAlignment != getRawTextAlignment()) {
23496            // Reset the current and resolved text alignment
23497            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23498            resetResolvedTextAlignment();
23499            // Set the new text alignment
23500            mPrivateFlags2 |=
23501                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23502            // Do resolution
23503            resolveTextAlignment();
23504            // Notify change
23505            onRtlPropertiesChanged(getLayoutDirection());
23506            // Refresh
23507            requestLayout();
23508            invalidate(true);
23509        }
23510    }
23511
23512    /**
23513     * Return the resolved text alignment.
23514     *
23515     * @return the resolved text alignment. Returns one of:
23516     *
23517     * {@link #TEXT_ALIGNMENT_GRAVITY},
23518     * {@link #TEXT_ALIGNMENT_CENTER},
23519     * {@link #TEXT_ALIGNMENT_TEXT_START},
23520     * {@link #TEXT_ALIGNMENT_TEXT_END},
23521     * {@link #TEXT_ALIGNMENT_VIEW_START},
23522     * {@link #TEXT_ALIGNMENT_VIEW_END}
23523     *
23524     * @attr ref android.R.styleable#View_textAlignment
23525     */
23526    @ViewDebug.ExportedProperty(category = "text", mapping = {
23527            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23528            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23529            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23530            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23531            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23532            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23533            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23534    })
23535    @TextAlignment
23536    public int getTextAlignment() {
23537        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
23538                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
23539    }
23540
23541    /**
23542     * Resolve the text alignment.
23543     *
23544     * @return true if resolution has been done, false otherwise.
23545     *
23546     * @hide
23547     */
23548    public boolean resolveTextAlignment() {
23549        // Reset any previous text alignment resolution
23550        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23551
23552        if (hasRtlSupport()) {
23553            // Set resolved text alignment flag depending on text alignment flag
23554            final int textAlignment = getRawTextAlignment();
23555            switch (textAlignment) {
23556                case TEXT_ALIGNMENT_INHERIT:
23557                    // Check if we can resolve the text alignment
23558                    if (!canResolveTextAlignment()) {
23559                        // We cannot do the resolution if there is no parent so use the default
23560                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23561                        // Resolution will need to happen again later
23562                        return false;
23563                    }
23564
23565                    // Parent has not yet resolved, so we still return the default
23566                    try {
23567                        if (!mParent.isTextAlignmentResolved()) {
23568                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23569                            // Resolution will need to happen again later
23570                            return false;
23571                        }
23572                    } catch (AbstractMethodError e) {
23573                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23574                                " does not fully implement ViewParent", e);
23575                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
23576                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23577                        return true;
23578                    }
23579
23580                    int parentResolvedTextAlignment;
23581                    try {
23582                        parentResolvedTextAlignment = mParent.getTextAlignment();
23583                    } catch (AbstractMethodError e) {
23584                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23585                                " does not fully implement ViewParent", e);
23586                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
23587                    }
23588                    switch (parentResolvedTextAlignment) {
23589                        case TEXT_ALIGNMENT_GRAVITY:
23590                        case TEXT_ALIGNMENT_TEXT_START:
23591                        case TEXT_ALIGNMENT_TEXT_END:
23592                        case TEXT_ALIGNMENT_CENTER:
23593                        case TEXT_ALIGNMENT_VIEW_START:
23594                        case TEXT_ALIGNMENT_VIEW_END:
23595                            // Resolved text alignment is the same as the parent resolved
23596                            // text alignment
23597                            mPrivateFlags2 |=
23598                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23599                            break;
23600                        default:
23601                            // Use default resolved text alignment
23602                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23603                    }
23604                    break;
23605                case TEXT_ALIGNMENT_GRAVITY:
23606                case TEXT_ALIGNMENT_TEXT_START:
23607                case TEXT_ALIGNMENT_TEXT_END:
23608                case TEXT_ALIGNMENT_CENTER:
23609                case TEXT_ALIGNMENT_VIEW_START:
23610                case TEXT_ALIGNMENT_VIEW_END:
23611                    // Resolved text alignment is the same as text alignment
23612                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
23613                    break;
23614                default:
23615                    // Use default resolved text alignment
23616                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23617            }
23618        } else {
23619            // Use default resolved text alignment
23620            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23621        }
23622
23623        // Set the resolved
23624        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23625        return true;
23626    }
23627
23628    /**
23629     * Check if text alignment resolution can be done.
23630     *
23631     * @return true if text alignment resolution can be done otherwise return false.
23632     */
23633    public boolean canResolveTextAlignment() {
23634        switch (getRawTextAlignment()) {
23635            case TEXT_DIRECTION_INHERIT:
23636                if (mParent != null) {
23637                    try {
23638                        return mParent.canResolveTextAlignment();
23639                    } catch (AbstractMethodError e) {
23640                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23641                                " does not fully implement ViewParent", e);
23642                    }
23643                }
23644                return false;
23645
23646            default:
23647                return true;
23648        }
23649    }
23650
23651    /**
23652     * Reset resolved text alignment. Text alignment will be resolved during a call to
23653     * {@link #onMeasure(int, int)}.
23654     *
23655     * @hide
23656     */
23657    public void resetResolvedTextAlignment() {
23658        // Reset any previous text alignment resolution
23659        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23660        // Set to default
23661        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23662    }
23663
23664    /**
23665     * @return true if text alignment is inherited.
23666     *
23667     * @hide
23668     */
23669    public boolean isTextAlignmentInherited() {
23670        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
23671    }
23672
23673    /**
23674     * @return true if text alignment is resolved.
23675     */
23676    public boolean isTextAlignmentResolved() {
23677        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
23678    }
23679
23680    /**
23681     * Generate a value suitable for use in {@link #setId(int)}.
23682     * This value will not collide with ID values generated at build time by aapt for R.id.
23683     *
23684     * @return a generated ID value
23685     */
23686    public static int generateViewId() {
23687        for (;;) {
23688            final int result = sNextGeneratedId.get();
23689            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
23690            int newValue = result + 1;
23691            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
23692            if (sNextGeneratedId.compareAndSet(result, newValue)) {
23693                return result;
23694            }
23695        }
23696    }
23697
23698    private static boolean isViewIdGenerated(int id) {
23699        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
23700    }
23701
23702    /**
23703     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
23704     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
23705     *                           a normal View or a ViewGroup with
23706     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
23707     * @hide
23708     */
23709    public void captureTransitioningViews(List<View> transitioningViews) {
23710        if (getVisibility() == View.VISIBLE) {
23711            transitioningViews.add(this);
23712        }
23713    }
23714
23715    /**
23716     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
23717     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
23718     * @hide
23719     */
23720    public void findNamedViews(Map<String, View> namedElements) {
23721        if (getVisibility() == VISIBLE || mGhostView != null) {
23722            String transitionName = getTransitionName();
23723            if (transitionName != null) {
23724                namedElements.put(transitionName, this);
23725            }
23726        }
23727    }
23728
23729    /**
23730     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
23731     * The default implementation does not care the location or event types, but some subclasses
23732     * may use it (such as WebViews).
23733     * @param event The MotionEvent from a mouse
23734     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
23735     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
23736     * @see PointerIcon
23737     */
23738    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
23739        final float x = event.getX(pointerIndex);
23740        final float y = event.getY(pointerIndex);
23741        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
23742            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
23743        }
23744        return mPointerIcon;
23745    }
23746
23747    /**
23748     * Set the pointer icon for the current view.
23749     * Passing {@code null} will restore the pointer icon to its default value.
23750     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
23751     */
23752    public void setPointerIcon(PointerIcon pointerIcon) {
23753        mPointerIcon = pointerIcon;
23754        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
23755            return;
23756        }
23757        try {
23758            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
23759        } catch (RemoteException e) {
23760        }
23761    }
23762
23763    /**
23764     * Gets the pointer icon for the current view.
23765     */
23766    public PointerIcon getPointerIcon() {
23767        return mPointerIcon;
23768    }
23769
23770    /**
23771     * Checks pointer capture status.
23772     *
23773     * @return true if the view has pointer capture.
23774     * @see #requestPointerCapture()
23775     * @see #hasPointerCapture()
23776     */
23777    public boolean hasPointerCapture() {
23778        final ViewRootImpl viewRootImpl = getViewRootImpl();
23779        if (viewRootImpl == null) {
23780            return false;
23781        }
23782        return viewRootImpl.hasPointerCapture();
23783    }
23784
23785    /**
23786     * Requests pointer capture mode.
23787     * <p>
23788     * When the window has pointer capture, the mouse pointer icon will disappear and will not
23789     * change its position. Further mouse will be dispatched with the source
23790     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
23791     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
23792     * (touchscreens, or stylus) will not be affected.
23793     * <p>
23794     * If the window already has pointer capture, this call does nothing.
23795     * <p>
23796     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
23797     * automatically when the window loses focus.
23798     *
23799     * @see #releasePointerCapture()
23800     * @see #hasPointerCapture()
23801     */
23802    public void requestPointerCapture() {
23803        final ViewRootImpl viewRootImpl = getViewRootImpl();
23804        if (viewRootImpl != null) {
23805            viewRootImpl.requestPointerCapture(true);
23806        }
23807    }
23808
23809
23810    /**
23811     * Releases the pointer capture.
23812     * <p>
23813     * If the window does not have pointer capture, this call will do nothing.
23814     * @see #requestPointerCapture()
23815     * @see #hasPointerCapture()
23816     */
23817    public void releasePointerCapture() {
23818        final ViewRootImpl viewRootImpl = getViewRootImpl();
23819        if (viewRootImpl != null) {
23820            viewRootImpl.requestPointerCapture(false);
23821        }
23822    }
23823
23824    /**
23825     * Called when the window has just acquired or lost pointer capture.
23826     *
23827     * @param hasCapture True if the view now has pointerCapture, false otherwise.
23828     */
23829    @CallSuper
23830    public void onPointerCaptureChange(boolean hasCapture) {
23831    }
23832
23833    /**
23834     * @see #onPointerCaptureChange
23835     */
23836    public void dispatchPointerCaptureChanged(boolean hasCapture) {
23837        onPointerCaptureChange(hasCapture);
23838    }
23839
23840    /**
23841     * Implement this method to handle captured pointer events
23842     *
23843     * @param event The captured pointer event.
23844     * @return True if the event was handled, false otherwise.
23845     * @see #requestPointerCapture()
23846     */
23847    public boolean onCapturedPointerEvent(MotionEvent event) {
23848        return false;
23849    }
23850
23851    /**
23852     * Interface definition for a callback to be invoked when a captured pointer event
23853     * is being dispatched this view. The callback will be invoked before the event is
23854     * given to the view.
23855     */
23856    public interface OnCapturedPointerListener {
23857        /**
23858         * Called when a captured pointer event is dispatched to a view.
23859         * @param view The view this event has been dispatched to.
23860         * @param event The captured event.
23861         * @return True if the listener has consumed the event, false otherwise.
23862         */
23863        boolean onCapturedPointer(View view, MotionEvent event);
23864    }
23865
23866    /**
23867     * Set a listener to receive callbacks when the pointer capture state of a view changes.
23868     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
23869     */
23870    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
23871        getListenerInfo().mOnCapturedPointerListener = l;
23872    }
23873
23874    // Properties
23875    //
23876    /**
23877     * A Property wrapper around the <code>alpha</code> functionality handled by the
23878     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
23879     */
23880    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
23881        @Override
23882        public void setValue(View object, float value) {
23883            object.setAlpha(value);
23884        }
23885
23886        @Override
23887        public Float get(View object) {
23888            return object.getAlpha();
23889        }
23890    };
23891
23892    /**
23893     * A Property wrapper around the <code>translationX</code> functionality handled by the
23894     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
23895     */
23896    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
23897        @Override
23898        public void setValue(View object, float value) {
23899            object.setTranslationX(value);
23900        }
23901
23902                @Override
23903        public Float get(View object) {
23904            return object.getTranslationX();
23905        }
23906    };
23907
23908    /**
23909     * A Property wrapper around the <code>translationY</code> functionality handled by the
23910     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
23911     */
23912    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
23913        @Override
23914        public void setValue(View object, float value) {
23915            object.setTranslationY(value);
23916        }
23917
23918        @Override
23919        public Float get(View object) {
23920            return object.getTranslationY();
23921        }
23922    };
23923
23924    /**
23925     * A Property wrapper around the <code>translationZ</code> functionality handled by the
23926     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
23927     */
23928    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
23929        @Override
23930        public void setValue(View object, float value) {
23931            object.setTranslationZ(value);
23932        }
23933
23934        @Override
23935        public Float get(View object) {
23936            return object.getTranslationZ();
23937        }
23938    };
23939
23940    /**
23941     * A Property wrapper around the <code>x</code> functionality handled by the
23942     * {@link View#setX(float)} and {@link View#getX()} methods.
23943     */
23944    public static final Property<View, Float> X = new FloatProperty<View>("x") {
23945        @Override
23946        public void setValue(View object, float value) {
23947            object.setX(value);
23948        }
23949
23950        @Override
23951        public Float get(View object) {
23952            return object.getX();
23953        }
23954    };
23955
23956    /**
23957     * A Property wrapper around the <code>y</code> functionality handled by the
23958     * {@link View#setY(float)} and {@link View#getY()} methods.
23959     */
23960    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
23961        @Override
23962        public void setValue(View object, float value) {
23963            object.setY(value);
23964        }
23965
23966        @Override
23967        public Float get(View object) {
23968            return object.getY();
23969        }
23970    };
23971
23972    /**
23973     * A Property wrapper around the <code>z</code> functionality handled by the
23974     * {@link View#setZ(float)} and {@link View#getZ()} methods.
23975     */
23976    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
23977        @Override
23978        public void setValue(View object, float value) {
23979            object.setZ(value);
23980        }
23981
23982        @Override
23983        public Float get(View object) {
23984            return object.getZ();
23985        }
23986    };
23987
23988    /**
23989     * A Property wrapper around the <code>rotation</code> functionality handled by the
23990     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
23991     */
23992    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
23993        @Override
23994        public void setValue(View object, float value) {
23995            object.setRotation(value);
23996        }
23997
23998        @Override
23999        public Float get(View object) {
24000            return object.getRotation();
24001        }
24002    };
24003
24004    /**
24005     * A Property wrapper around the <code>rotationX</code> functionality handled by the
24006     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
24007     */
24008    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
24009        @Override
24010        public void setValue(View object, float value) {
24011            object.setRotationX(value);
24012        }
24013
24014        @Override
24015        public Float get(View object) {
24016            return object.getRotationX();
24017        }
24018    };
24019
24020    /**
24021     * A Property wrapper around the <code>rotationY</code> functionality handled by the
24022     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
24023     */
24024    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
24025        @Override
24026        public void setValue(View object, float value) {
24027            object.setRotationY(value);
24028        }
24029
24030        @Override
24031        public Float get(View object) {
24032            return object.getRotationY();
24033        }
24034    };
24035
24036    /**
24037     * A Property wrapper around the <code>scaleX</code> functionality handled by the
24038     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
24039     */
24040    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
24041        @Override
24042        public void setValue(View object, float value) {
24043            object.setScaleX(value);
24044        }
24045
24046        @Override
24047        public Float get(View object) {
24048            return object.getScaleX();
24049        }
24050    };
24051
24052    /**
24053     * A Property wrapper around the <code>scaleY</code> functionality handled by the
24054     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
24055     */
24056    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
24057        @Override
24058        public void setValue(View object, float value) {
24059            object.setScaleY(value);
24060        }
24061
24062        @Override
24063        public Float get(View object) {
24064            return object.getScaleY();
24065        }
24066    };
24067
24068    /**
24069     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
24070     * Each MeasureSpec represents a requirement for either the width or the height.
24071     * A MeasureSpec is comprised of a size and a mode. There are three possible
24072     * modes:
24073     * <dl>
24074     * <dt>UNSPECIFIED</dt>
24075     * <dd>
24076     * The parent has not imposed any constraint on the child. It can be whatever size
24077     * it wants.
24078     * </dd>
24079     *
24080     * <dt>EXACTLY</dt>
24081     * <dd>
24082     * The parent has determined an exact size for the child. The child is going to be
24083     * given those bounds regardless of how big it wants to be.
24084     * </dd>
24085     *
24086     * <dt>AT_MOST</dt>
24087     * <dd>
24088     * The child can be as large as it wants up to the specified size.
24089     * </dd>
24090     * </dl>
24091     *
24092     * MeasureSpecs are implemented as ints to reduce object allocation. This class
24093     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
24094     */
24095    public static class MeasureSpec {
24096        private static final int MODE_SHIFT = 30;
24097        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
24098
24099        /** @hide */
24100        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
24101        @Retention(RetentionPolicy.SOURCE)
24102        public @interface MeasureSpecMode {}
24103
24104        /**
24105         * Measure specification mode: The parent has not imposed any constraint
24106         * on the child. It can be whatever size it wants.
24107         */
24108        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
24109
24110        /**
24111         * Measure specification mode: The parent has determined an exact size
24112         * for the child. The child is going to be given those bounds regardless
24113         * of how big it wants to be.
24114         */
24115        public static final int EXACTLY     = 1 << MODE_SHIFT;
24116
24117        /**
24118         * Measure specification mode: The child can be as large as it wants up
24119         * to the specified size.
24120         */
24121        public static final int AT_MOST     = 2 << MODE_SHIFT;
24122
24123        /**
24124         * Creates a measure specification based on the supplied size and mode.
24125         *
24126         * The mode must always be one of the following:
24127         * <ul>
24128         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
24129         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
24130         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
24131         * </ul>
24132         *
24133         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
24134         * implementation was such that the order of arguments did not matter
24135         * and overflow in either value could impact the resulting MeasureSpec.
24136         * {@link android.widget.RelativeLayout} was affected by this bug.
24137         * Apps targeting API levels greater than 17 will get the fixed, more strict
24138         * behavior.</p>
24139         *
24140         * @param size the size of the measure specification
24141         * @param mode the mode of the measure specification
24142         * @return the measure specification based on size and mode
24143         */
24144        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
24145                                          @MeasureSpecMode int mode) {
24146            if (sUseBrokenMakeMeasureSpec) {
24147                return size + mode;
24148            } else {
24149                return (size & ~MODE_MASK) | (mode & MODE_MASK);
24150            }
24151        }
24152
24153        /**
24154         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
24155         * will automatically get a size of 0. Older apps expect this.
24156         *
24157         * @hide internal use only for compatibility with system widgets and older apps
24158         */
24159        public static int makeSafeMeasureSpec(int size, int mode) {
24160            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
24161                return 0;
24162            }
24163            return makeMeasureSpec(size, mode);
24164        }
24165
24166        /**
24167         * Extracts the mode from the supplied measure specification.
24168         *
24169         * @param measureSpec the measure specification to extract the mode from
24170         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
24171         *         {@link android.view.View.MeasureSpec#AT_MOST} or
24172         *         {@link android.view.View.MeasureSpec#EXACTLY}
24173         */
24174        @MeasureSpecMode
24175        public static int getMode(int measureSpec) {
24176            //noinspection ResourceType
24177            return (measureSpec & MODE_MASK);
24178        }
24179
24180        /**
24181         * Extracts the size from the supplied measure specification.
24182         *
24183         * @param measureSpec the measure specification to extract the size from
24184         * @return the size in pixels defined in the supplied measure specification
24185         */
24186        public static int getSize(int measureSpec) {
24187            return (measureSpec & ~MODE_MASK);
24188        }
24189
24190        static int adjust(int measureSpec, int delta) {
24191            final int mode = getMode(measureSpec);
24192            int size = getSize(measureSpec);
24193            if (mode == UNSPECIFIED) {
24194                // No need to adjust size for UNSPECIFIED mode.
24195                return makeMeasureSpec(size, UNSPECIFIED);
24196            }
24197            size += delta;
24198            if (size < 0) {
24199                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
24200                        ") spec: " + toString(measureSpec) + " delta: " + delta);
24201                size = 0;
24202            }
24203            return makeMeasureSpec(size, mode);
24204        }
24205
24206        /**
24207         * Returns a String representation of the specified measure
24208         * specification.
24209         *
24210         * @param measureSpec the measure specification to convert to a String
24211         * @return a String with the following format: "MeasureSpec: MODE SIZE"
24212         */
24213        public static String toString(int measureSpec) {
24214            int mode = getMode(measureSpec);
24215            int size = getSize(measureSpec);
24216
24217            StringBuilder sb = new StringBuilder("MeasureSpec: ");
24218
24219            if (mode == UNSPECIFIED)
24220                sb.append("UNSPECIFIED ");
24221            else if (mode == EXACTLY)
24222                sb.append("EXACTLY ");
24223            else if (mode == AT_MOST)
24224                sb.append("AT_MOST ");
24225            else
24226                sb.append(mode).append(" ");
24227
24228            sb.append(size);
24229            return sb.toString();
24230        }
24231    }
24232
24233    private final class CheckForLongPress implements Runnable {
24234        private int mOriginalWindowAttachCount;
24235        private float mX;
24236        private float mY;
24237        private boolean mOriginalPressedState;
24238
24239        @Override
24240        public void run() {
24241            if ((mOriginalPressedState == isPressed()) && (mParent != null)
24242                    && mOriginalWindowAttachCount == mWindowAttachCount) {
24243                if (performLongClick(mX, mY)) {
24244                    mHasPerformedLongPress = true;
24245                }
24246            }
24247        }
24248
24249        public void setAnchor(float x, float y) {
24250            mX = x;
24251            mY = y;
24252        }
24253
24254        public void rememberWindowAttachCount() {
24255            mOriginalWindowAttachCount = mWindowAttachCount;
24256        }
24257
24258        public void rememberPressedState() {
24259            mOriginalPressedState = isPressed();
24260        }
24261    }
24262
24263    private final class CheckForTap implements Runnable {
24264        public float x;
24265        public float y;
24266
24267        @Override
24268        public void run() {
24269            mPrivateFlags &= ~PFLAG_PREPRESSED;
24270            setPressed(true, x, y);
24271            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
24272        }
24273    }
24274
24275    private final class PerformClick implements Runnable {
24276        @Override
24277        public void run() {
24278            performClick();
24279        }
24280    }
24281
24282    /**
24283     * This method returns a ViewPropertyAnimator object, which can be used to animate
24284     * specific properties on this View.
24285     *
24286     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
24287     */
24288    public ViewPropertyAnimator animate() {
24289        if (mAnimator == null) {
24290            mAnimator = new ViewPropertyAnimator(this);
24291        }
24292        return mAnimator;
24293    }
24294
24295    /**
24296     * Sets the name of the View to be used to identify Views in Transitions.
24297     * Names should be unique in the View hierarchy.
24298     *
24299     * @param transitionName The name of the View to uniquely identify it for Transitions.
24300     */
24301    public final void setTransitionName(String transitionName) {
24302        mTransitionName = transitionName;
24303    }
24304
24305    /**
24306     * Returns the name of the View to be used to identify Views in Transitions.
24307     * Names should be unique in the View hierarchy.
24308     *
24309     * <p>This returns null if the View has not been given a name.</p>
24310     *
24311     * @return The name used of the View to be used to identify Views in Transitions or null
24312     * if no name has been given.
24313     */
24314    @ViewDebug.ExportedProperty
24315    public String getTransitionName() {
24316        return mTransitionName;
24317    }
24318
24319    /**
24320     * @hide
24321     */
24322    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24323        // Do nothing.
24324    }
24325
24326    /**
24327     * Interface definition for a callback to be invoked when a hardware key event is
24328     * dispatched to this view. The callback will be invoked before the key event is
24329     * given to the view. This is only useful for hardware keyboards; a software input
24330     * method has no obligation to trigger this listener.
24331     */
24332    public interface OnKeyListener {
24333        /**
24334         * Called when a hardware key is dispatched to a view. This allows listeners to
24335         * get a chance to respond before the target view.
24336         * <p>Key presses in software keyboards will generally NOT trigger this method,
24337         * although some may elect to do so in some situations. Do not assume a
24338         * software input method has to be key-based; even if it is, it may use key presses
24339         * in a different way than you expect, so there is no way to reliably catch soft
24340         * input key presses.
24341         *
24342         * @param v The view the key has been dispatched to.
24343         * @param keyCode The code for the physical key that was pressed
24344         * @param event The KeyEvent object containing full information about
24345         *        the event.
24346         * @return True if the listener has consumed the event, false otherwise.
24347         */
24348        boolean onKey(View v, int keyCode, KeyEvent event);
24349    }
24350
24351    /**
24352     * Interface definition for a callback to be invoked when a touch event is
24353     * dispatched to this view. The callback will be invoked before the touch
24354     * event is given to the view.
24355     */
24356    public interface OnTouchListener {
24357        /**
24358         * Called when a touch event is dispatched to a view. This allows listeners to
24359         * get a chance to respond before the target view.
24360         *
24361         * @param v The view the touch event has been dispatched to.
24362         * @param event The MotionEvent object containing full information about
24363         *        the event.
24364         * @return True if the listener has consumed the event, false otherwise.
24365         */
24366        boolean onTouch(View v, MotionEvent event);
24367    }
24368
24369    /**
24370     * Interface definition for a callback to be invoked when a hover event is
24371     * dispatched to this view. The callback will be invoked before the hover
24372     * event is given to the view.
24373     */
24374    public interface OnHoverListener {
24375        /**
24376         * Called when a hover event is dispatched to a view. This allows listeners to
24377         * get a chance to respond before the target view.
24378         *
24379         * @param v The view the hover event has been dispatched to.
24380         * @param event The MotionEvent object containing full information about
24381         *        the event.
24382         * @return True if the listener has consumed the event, false otherwise.
24383         */
24384        boolean onHover(View v, MotionEvent event);
24385    }
24386
24387    /**
24388     * Interface definition for a callback to be invoked when a generic motion event is
24389     * dispatched to this view. The callback will be invoked before the generic motion
24390     * event is given to the view.
24391     */
24392    public interface OnGenericMotionListener {
24393        /**
24394         * Called when a generic motion event is dispatched to a view. This allows listeners to
24395         * get a chance to respond before the target view.
24396         *
24397         * @param v The view the generic motion event has been dispatched to.
24398         * @param event The MotionEvent object containing full information about
24399         *        the event.
24400         * @return True if the listener has consumed the event, false otherwise.
24401         */
24402        boolean onGenericMotion(View v, MotionEvent event);
24403    }
24404
24405    /**
24406     * Interface definition for a callback to be invoked when a view has been clicked and held.
24407     */
24408    public interface OnLongClickListener {
24409        /**
24410         * Called when a view has been clicked and held.
24411         *
24412         * @param v The view that was clicked and held.
24413         *
24414         * @return true if the callback consumed the long click, false otherwise.
24415         */
24416        boolean onLongClick(View v);
24417    }
24418
24419    /**
24420     * Interface definition for a callback to be invoked when a drag is being dispatched
24421     * to this view.  The callback will be invoked before the hosting view's own
24422     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24423     * onDrag(event) behavior, it should return 'false' from this callback.
24424     *
24425     * <div class="special reference">
24426     * <h3>Developer Guides</h3>
24427     * <p>For a guide to implementing drag and drop features, read the
24428     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24429     * </div>
24430     */
24431    public interface OnDragListener {
24432        /**
24433         * Called when a drag event is dispatched to a view. This allows listeners
24434         * to get a chance to override base View behavior.
24435         *
24436         * @param v The View that received the drag event.
24437         * @param event The {@link android.view.DragEvent} object for the drag event.
24438         * @return {@code true} if the drag event was handled successfully, or {@code false}
24439         * if the drag event was not handled. Note that {@code false} will trigger the View
24440         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24441         */
24442        boolean onDrag(View v, DragEvent event);
24443    }
24444
24445    /**
24446     * Interface definition for a callback to be invoked when the focus state of
24447     * a view changed.
24448     */
24449    public interface OnFocusChangeListener {
24450        /**
24451         * Called when the focus state of a view has changed.
24452         *
24453         * @param v The view whose state has changed.
24454         * @param hasFocus The new focus state of v.
24455         */
24456        void onFocusChange(View v, boolean hasFocus);
24457    }
24458
24459    /**
24460     * Interface definition for a callback to be invoked when a view is clicked.
24461     */
24462    public interface OnClickListener {
24463        /**
24464         * Called when a view has been clicked.
24465         *
24466         * @param v The view that was clicked.
24467         */
24468        void onClick(View v);
24469    }
24470
24471    /**
24472     * Interface definition for a callback to be invoked when a view is context clicked.
24473     */
24474    public interface OnContextClickListener {
24475        /**
24476         * Called when a view is context clicked.
24477         *
24478         * @param v The view that has been context clicked.
24479         * @return true if the callback consumed the context click, false otherwise.
24480         */
24481        boolean onContextClick(View v);
24482    }
24483
24484    /**
24485     * Interface definition for a callback to be invoked when the context menu
24486     * for this view is being built.
24487     */
24488    public interface OnCreateContextMenuListener {
24489        /**
24490         * Called when the context menu for this view is being built. It is not
24491         * safe to hold onto the menu after this method returns.
24492         *
24493         * @param menu The context menu that is being built
24494         * @param v The view for which the context menu is being built
24495         * @param menuInfo Extra information about the item for which the
24496         *            context menu should be shown. This information will vary
24497         *            depending on the class of v.
24498         */
24499        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24500    }
24501
24502    /**
24503     * Interface definition for a callback to be invoked when the status bar changes
24504     * visibility.  This reports <strong>global</strong> changes to the system UI
24505     * state, not what the application is requesting.
24506     *
24507     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
24508     */
24509    public interface OnSystemUiVisibilityChangeListener {
24510        /**
24511         * Called when the status bar changes visibility because of a call to
24512         * {@link View#setSystemUiVisibility(int)}.
24513         *
24514         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
24515         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
24516         * This tells you the <strong>global</strong> state of these UI visibility
24517         * flags, not what your app is currently applying.
24518         */
24519        public void onSystemUiVisibilityChange(int visibility);
24520    }
24521
24522    /**
24523     * Interface definition for a callback to be invoked when this view is attached
24524     * or detached from its window.
24525     */
24526    public interface OnAttachStateChangeListener {
24527        /**
24528         * Called when the view is attached to a window.
24529         * @param v The view that was attached
24530         */
24531        public void onViewAttachedToWindow(View v);
24532        /**
24533         * Called when the view is detached from a window.
24534         * @param v The view that was detached
24535         */
24536        public void onViewDetachedFromWindow(View v);
24537    }
24538
24539    /**
24540     * Listener for applying window insets on a view in a custom way.
24541     *
24542     * <p>Apps may choose to implement this interface if they want to apply custom policy
24543     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
24544     * is set, its
24545     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
24546     * method will be called instead of the View's own
24547     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
24548     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
24549     * the View's normal behavior as part of its own.</p>
24550     */
24551    public interface OnApplyWindowInsetsListener {
24552        /**
24553         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
24554         * on a View, this listener method will be called instead of the view's own
24555         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
24556         *
24557         * @param v The view applying window insets
24558         * @param insets The insets to apply
24559         * @return The insets supplied, minus any insets that were consumed
24560         */
24561        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
24562    }
24563
24564    private final class UnsetPressedState implements Runnable {
24565        @Override
24566        public void run() {
24567            setPressed(false);
24568        }
24569    }
24570
24571    /**
24572     * When a view becomes invisible checks if autofill considers the view invisible too. This
24573     * happens after the regular removal operation to make sure the operation is finished by the
24574     * time this is called.
24575     */
24576    private static class VisibilityChangeForAutofillHandler extends Handler {
24577        private final AutofillManager mAfm;
24578        private final View mView;
24579
24580        private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
24581                @NonNull View view) {
24582            mAfm = afm;
24583            mView = view;
24584        }
24585
24586        @Override
24587        public void handleMessage(Message msg) {
24588            mAfm.notifyViewVisibilityChange(mView, mView.isShown());
24589        }
24590    }
24591
24592    /**
24593     * Base class for derived classes that want to save and restore their own
24594     * state in {@link android.view.View#onSaveInstanceState()}.
24595     */
24596    public static class BaseSavedState extends AbsSavedState {
24597        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
24598        static final int IS_AUTOFILLED = 0b10;
24599        static final int ACCESSIBILITY_ID = 0b100;
24600
24601        // Flags that describe what data in this state is valid
24602        int mSavedData;
24603        String mStartActivityRequestWhoSaved;
24604        boolean mIsAutofilled;
24605        int mAccessibilityViewId;
24606
24607        /**
24608         * Constructor used when reading from a parcel. Reads the state of the superclass.
24609         *
24610         * @param source parcel to read from
24611         */
24612        public BaseSavedState(Parcel source) {
24613            this(source, null);
24614        }
24615
24616        /**
24617         * Constructor used when reading from a parcel using a given class loader.
24618         * Reads the state of the superclass.
24619         *
24620         * @param source parcel to read from
24621         * @param loader ClassLoader to use for reading
24622         */
24623        public BaseSavedState(Parcel source, ClassLoader loader) {
24624            super(source, loader);
24625            mSavedData = source.readInt();
24626            mStartActivityRequestWhoSaved = source.readString();
24627            mIsAutofilled = source.readBoolean();
24628            mAccessibilityViewId = source.readInt();
24629        }
24630
24631        /**
24632         * Constructor called by derived classes when creating their SavedState objects
24633         *
24634         * @param superState The state of the superclass of this view
24635         */
24636        public BaseSavedState(Parcelable superState) {
24637            super(superState);
24638        }
24639
24640        @Override
24641        public void writeToParcel(Parcel out, int flags) {
24642            super.writeToParcel(out, flags);
24643
24644            out.writeInt(mSavedData);
24645            out.writeString(mStartActivityRequestWhoSaved);
24646            out.writeBoolean(mIsAutofilled);
24647            out.writeInt(mAccessibilityViewId);
24648        }
24649
24650        public static final Parcelable.Creator<BaseSavedState> CREATOR
24651                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
24652            @Override
24653            public BaseSavedState createFromParcel(Parcel in) {
24654                return new BaseSavedState(in);
24655            }
24656
24657            @Override
24658            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
24659                return new BaseSavedState(in, loader);
24660            }
24661
24662            @Override
24663            public BaseSavedState[] newArray(int size) {
24664                return new BaseSavedState[size];
24665            }
24666        };
24667    }
24668
24669    /**
24670     * A set of information given to a view when it is attached to its parent
24671     * window.
24672     */
24673    final static class AttachInfo {
24674        interface Callbacks {
24675            void playSoundEffect(int effectId);
24676            boolean performHapticFeedback(int effectId, boolean always);
24677        }
24678
24679        /**
24680         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
24681         * to a Handler. This class contains the target (View) to invalidate and
24682         * the coordinates of the dirty rectangle.
24683         *
24684         * For performance purposes, this class also implements a pool of up to
24685         * POOL_LIMIT objects that get reused. This reduces memory allocations
24686         * whenever possible.
24687         */
24688        static class InvalidateInfo {
24689            private static final int POOL_LIMIT = 10;
24690
24691            private static final SynchronizedPool<InvalidateInfo> sPool =
24692                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
24693
24694            View target;
24695
24696            int left;
24697            int top;
24698            int right;
24699            int bottom;
24700
24701            public static InvalidateInfo obtain() {
24702                InvalidateInfo instance = sPool.acquire();
24703                return (instance != null) ? instance : new InvalidateInfo();
24704            }
24705
24706            public void recycle() {
24707                target = null;
24708                sPool.release(this);
24709            }
24710        }
24711
24712        final IWindowSession mSession;
24713
24714        final IWindow mWindow;
24715
24716        final IBinder mWindowToken;
24717
24718        Display mDisplay;
24719
24720        final Callbacks mRootCallbacks;
24721
24722        IWindowId mIWindowId;
24723        WindowId mWindowId;
24724
24725        /**
24726         * The top view of the hierarchy.
24727         */
24728        View mRootView;
24729
24730        IBinder mPanelParentWindowToken;
24731
24732        boolean mHardwareAccelerated;
24733        boolean mHardwareAccelerationRequested;
24734        ThreadedRenderer mThreadedRenderer;
24735        List<RenderNode> mPendingAnimatingRenderNodes;
24736
24737        /**
24738         * The state of the display to which the window is attached, as reported
24739         * by {@link Display#getState()}.  Note that the display state constants
24740         * declared by {@link Display} do not exactly line up with the screen state
24741         * constants declared by {@link View} (there are more display states than
24742         * screen states).
24743         */
24744        int mDisplayState = Display.STATE_UNKNOWN;
24745
24746        /**
24747         * Scale factor used by the compatibility mode
24748         */
24749        float mApplicationScale;
24750
24751        /**
24752         * Indicates whether the application is in compatibility mode
24753         */
24754        boolean mScalingRequired;
24755
24756        /**
24757         * Left position of this view's window
24758         */
24759        int mWindowLeft;
24760
24761        /**
24762         * Top position of this view's window
24763         */
24764        int mWindowTop;
24765
24766        /**
24767         * Indicates whether views need to use 32-bit drawing caches
24768         */
24769        boolean mUse32BitDrawingCache;
24770
24771        /**
24772         * For windows that are full-screen but using insets to layout inside
24773         * of the screen areas, these are the current insets to appear inside
24774         * the overscan area of the display.
24775         */
24776        final Rect mOverscanInsets = new Rect();
24777
24778        /**
24779         * For windows that are full-screen but using insets to layout inside
24780         * of the screen decorations, these are the current insets for the
24781         * content of the window.
24782         */
24783        final Rect mContentInsets = new Rect();
24784
24785        /**
24786         * For windows that are full-screen but using insets to layout inside
24787         * of the screen decorations, these are the current insets for the
24788         * actual visible parts of the window.
24789         */
24790        final Rect mVisibleInsets = new Rect();
24791
24792        /**
24793         * For windows that are full-screen but using insets to layout inside
24794         * of the screen decorations, these are the current insets for the
24795         * stable system windows.
24796         */
24797        final Rect mStableInsets = new Rect();
24798
24799        /**
24800         * For windows that include areas that are not covered by real surface these are the outsets
24801         * for real surface.
24802         */
24803        final Rect mOutsets = new Rect();
24804
24805        /**
24806         * In multi-window we force show the navigation bar. Because we don't want that the surface
24807         * size changes in this mode, we instead have a flag whether the navigation bar size should
24808         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
24809         */
24810        boolean mAlwaysConsumeNavBar;
24811
24812        /**
24813         * The internal insets given by this window.  This value is
24814         * supplied by the client (through
24815         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
24816         * be given to the window manager when changed to be used in laying
24817         * out windows behind it.
24818         */
24819        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
24820                = new ViewTreeObserver.InternalInsetsInfo();
24821
24822        /**
24823         * Set to true when mGivenInternalInsets is non-empty.
24824         */
24825        boolean mHasNonEmptyGivenInternalInsets;
24826
24827        /**
24828         * All views in the window's hierarchy that serve as scroll containers,
24829         * used to determine if the window can be resized or must be panned
24830         * to adjust for a soft input area.
24831         */
24832        final ArrayList<View> mScrollContainers = new ArrayList<View>();
24833
24834        final KeyEvent.DispatcherState mKeyDispatchState
24835                = new KeyEvent.DispatcherState();
24836
24837        /**
24838         * Indicates whether the view's window currently has the focus.
24839         */
24840        boolean mHasWindowFocus;
24841
24842        /**
24843         * The current visibility of the window.
24844         */
24845        int mWindowVisibility;
24846
24847        /**
24848         * Indicates the time at which drawing started to occur.
24849         */
24850        long mDrawingTime;
24851
24852        /**
24853         * Indicates whether or not ignoring the DIRTY_MASK flags.
24854         */
24855        boolean mIgnoreDirtyState;
24856
24857        /**
24858         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
24859         * to avoid clearing that flag prematurely.
24860         */
24861        boolean mSetIgnoreDirtyState = false;
24862
24863        /**
24864         * Indicates whether the view's window is currently in touch mode.
24865         */
24866        boolean mInTouchMode;
24867
24868        /**
24869         * Indicates whether the view has requested unbuffered input dispatching for the current
24870         * event stream.
24871         */
24872        boolean mUnbufferedDispatchRequested;
24873
24874        /**
24875         * Indicates that ViewAncestor should trigger a global layout change
24876         * the next time it performs a traversal
24877         */
24878        boolean mRecomputeGlobalAttributes;
24879
24880        /**
24881         * Always report new attributes at next traversal.
24882         */
24883        boolean mForceReportNewAttributes;
24884
24885        /**
24886         * Set during a traveral if any views want to keep the screen on.
24887         */
24888        boolean mKeepScreenOn;
24889
24890        /**
24891         * Set during a traveral if the light center needs to be updated.
24892         */
24893        boolean mNeedsUpdateLightCenter;
24894
24895        /**
24896         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
24897         */
24898        int mSystemUiVisibility;
24899
24900        /**
24901         * Hack to force certain system UI visibility flags to be cleared.
24902         */
24903        int mDisabledSystemUiVisibility;
24904
24905        /**
24906         * Last global system UI visibility reported by the window manager.
24907         */
24908        int mGlobalSystemUiVisibility = -1;
24909
24910        /**
24911         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
24912         * attached.
24913         */
24914        boolean mHasSystemUiListeners;
24915
24916        /**
24917         * Set if the window has requested to extend into the overscan region
24918         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
24919         */
24920        boolean mOverscanRequested;
24921
24922        /**
24923         * Set if the visibility of any views has changed.
24924         */
24925        boolean mViewVisibilityChanged;
24926
24927        /**
24928         * Set to true if a view has been scrolled.
24929         */
24930        boolean mViewScrollChanged;
24931
24932        /**
24933         * Set to true if high contrast mode enabled
24934         */
24935        boolean mHighContrastText;
24936
24937        /**
24938         * Set to true if a pointer event is currently being handled.
24939         */
24940        boolean mHandlingPointerEvent;
24941
24942        /**
24943         * Global to the view hierarchy used as a temporary for dealing with
24944         * x/y points in the transparent region computations.
24945         */
24946        final int[] mTransparentLocation = new int[2];
24947
24948        /**
24949         * Global to the view hierarchy used as a temporary for dealing with
24950         * x/y points in the ViewGroup.invalidateChild implementation.
24951         */
24952        final int[] mInvalidateChildLocation = new int[2];
24953
24954        /**
24955         * Global to the view hierarchy used as a temporary for dealing with
24956         * computing absolute on-screen location.
24957         */
24958        final int[] mTmpLocation = new int[2];
24959
24960        /**
24961         * Global to the view hierarchy used as a temporary for dealing with
24962         * x/y location when view is transformed.
24963         */
24964        final float[] mTmpTransformLocation = new float[2];
24965
24966        /**
24967         * The view tree observer used to dispatch global events like
24968         * layout, pre-draw, touch mode change, etc.
24969         */
24970        final ViewTreeObserver mTreeObserver;
24971
24972        /**
24973         * A Canvas used by the view hierarchy to perform bitmap caching.
24974         */
24975        Canvas mCanvas;
24976
24977        /**
24978         * The view root impl.
24979         */
24980        final ViewRootImpl mViewRootImpl;
24981
24982        /**
24983         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
24984         * handler can be used to pump events in the UI events queue.
24985         */
24986        final Handler mHandler;
24987
24988        /**
24989         * Temporary for use in computing invalidate rectangles while
24990         * calling up the hierarchy.
24991         */
24992        final Rect mTmpInvalRect = new Rect();
24993
24994        /**
24995         * Temporary for use in computing hit areas with transformed views
24996         */
24997        final RectF mTmpTransformRect = new RectF();
24998
24999        /**
25000         * Temporary for use in computing hit areas with transformed views
25001         */
25002        final RectF mTmpTransformRect1 = new RectF();
25003
25004        /**
25005         * Temporary list of rectanges.
25006         */
25007        final List<RectF> mTmpRectList = new ArrayList<>();
25008
25009        /**
25010         * Temporary for use in transforming invalidation rect
25011         */
25012        final Matrix mTmpMatrix = new Matrix();
25013
25014        /**
25015         * Temporary for use in transforming invalidation rect
25016         */
25017        final Transformation mTmpTransformation = new Transformation();
25018
25019        /**
25020         * Temporary for use in querying outlines from OutlineProviders
25021         */
25022        final Outline mTmpOutline = new Outline();
25023
25024        /**
25025         * Temporary list for use in collecting focusable descendents of a view.
25026         */
25027        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
25028
25029        /**
25030         * The id of the window for accessibility purposes.
25031         */
25032        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
25033
25034        /**
25035         * Flags related to accessibility processing.
25036         *
25037         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
25038         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
25039         */
25040        int mAccessibilityFetchFlags;
25041
25042        /**
25043         * The drawable for highlighting accessibility focus.
25044         */
25045        Drawable mAccessibilityFocusDrawable;
25046
25047        /**
25048         * The drawable for highlighting autofilled views.
25049         *
25050         * @see #isAutofilled()
25051         */
25052        Drawable mAutofilledDrawable;
25053
25054        /**
25055         * Show where the margins, bounds and layout bounds are for each view.
25056         */
25057        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
25058
25059        /**
25060         * Point used to compute visible regions.
25061         */
25062        final Point mPoint = new Point();
25063
25064        /**
25065         * Used to track which View originated a requestLayout() call, used when
25066         * requestLayout() is called during layout.
25067         */
25068        View mViewRequestingLayout;
25069
25070        /**
25071         * Used to track views that need (at least) a partial relayout at their current size
25072         * during the next traversal.
25073         */
25074        List<View> mPartialLayoutViews = new ArrayList<>();
25075
25076        /**
25077         * Swapped with mPartialLayoutViews during layout to avoid concurrent
25078         * modification. Lazily assigned during ViewRootImpl layout.
25079         */
25080        List<View> mEmptyPartialLayoutViews;
25081
25082        /**
25083         * Used to track the identity of the current drag operation.
25084         */
25085        IBinder mDragToken;
25086
25087        /**
25088         * The drag shadow surface for the current drag operation.
25089         */
25090        public Surface mDragSurface;
25091
25092
25093        /**
25094         * The view that currently has a tooltip displayed.
25095         */
25096        View mTooltipHost;
25097
25098        /**
25099         * Creates a new set of attachment information with the specified
25100         * events handler and thread.
25101         *
25102         * @param handler the events handler the view must use
25103         */
25104        AttachInfo(IWindowSession session, IWindow window, Display display,
25105                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
25106                Context context) {
25107            mSession = session;
25108            mWindow = window;
25109            mWindowToken = window.asBinder();
25110            mDisplay = display;
25111            mViewRootImpl = viewRootImpl;
25112            mHandler = handler;
25113            mRootCallbacks = effectPlayer;
25114            mTreeObserver = new ViewTreeObserver(context);
25115        }
25116    }
25117
25118    /**
25119     * <p>ScrollabilityCache holds various fields used by a View when scrolling
25120     * is supported. This avoids keeping too many unused fields in most
25121     * instances of View.</p>
25122     */
25123    private static class ScrollabilityCache implements Runnable {
25124
25125        /**
25126         * Scrollbars are not visible
25127         */
25128        public static final int OFF = 0;
25129
25130        /**
25131         * Scrollbars are visible
25132         */
25133        public static final int ON = 1;
25134
25135        /**
25136         * Scrollbars are fading away
25137         */
25138        public static final int FADING = 2;
25139
25140        public boolean fadeScrollBars;
25141
25142        public int fadingEdgeLength;
25143        public int scrollBarDefaultDelayBeforeFade;
25144        public int scrollBarFadeDuration;
25145
25146        public int scrollBarSize;
25147        public int scrollBarMinTouchTarget;
25148        public ScrollBarDrawable scrollBar;
25149        public float[] interpolatorValues;
25150        public View host;
25151
25152        public final Paint paint;
25153        public final Matrix matrix;
25154        public Shader shader;
25155
25156        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
25157
25158        private static final float[] OPAQUE = { 255 };
25159        private static final float[] TRANSPARENT = { 0.0f };
25160
25161        /**
25162         * When fading should start. This time moves into the future every time
25163         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
25164         */
25165        public long fadeStartTime;
25166
25167
25168        /**
25169         * The current state of the scrollbars: ON, OFF, or FADING
25170         */
25171        public int state = OFF;
25172
25173        private int mLastColor;
25174
25175        public final Rect mScrollBarBounds = new Rect();
25176        public final Rect mScrollBarTouchBounds = new Rect();
25177
25178        public static final int NOT_DRAGGING = 0;
25179        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
25180        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
25181        public int mScrollBarDraggingState = NOT_DRAGGING;
25182
25183        public float mScrollBarDraggingPos = 0;
25184
25185        public ScrollabilityCache(ViewConfiguration configuration, View host) {
25186            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
25187            scrollBarSize = configuration.getScaledScrollBarSize();
25188            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
25189            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
25190            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
25191
25192            paint = new Paint();
25193            matrix = new Matrix();
25194            // use use a height of 1, and then wack the matrix each time we
25195            // actually use it.
25196            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25197            paint.setShader(shader);
25198            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25199
25200            this.host = host;
25201        }
25202
25203        public void setFadeColor(int color) {
25204            if (color != mLastColor) {
25205                mLastColor = color;
25206
25207                if (color != 0) {
25208                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
25209                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
25210                    paint.setShader(shader);
25211                    // Restore the default transfer mode (src_over)
25212                    paint.setXfermode(null);
25213                } else {
25214                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25215                    paint.setShader(shader);
25216                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25217                }
25218            }
25219        }
25220
25221        public void run() {
25222            long now = AnimationUtils.currentAnimationTimeMillis();
25223            if (now >= fadeStartTime) {
25224
25225                // the animation fades the scrollbars out by changing
25226                // the opacity (alpha) from fully opaque to fully
25227                // transparent
25228                int nextFrame = (int) now;
25229                int framesCount = 0;
25230
25231                Interpolator interpolator = scrollBarInterpolator;
25232
25233                // Start opaque
25234                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
25235
25236                // End transparent
25237                nextFrame += scrollBarFadeDuration;
25238                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
25239
25240                state = FADING;
25241
25242                // Kick off the fade animation
25243                host.invalidate(true);
25244            }
25245        }
25246    }
25247
25248    /**
25249     * Resuable callback for sending
25250     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
25251     */
25252    private class SendViewScrolledAccessibilityEvent implements Runnable {
25253        public volatile boolean mIsPending;
25254
25255        public void run() {
25256            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
25257            mIsPending = false;
25258        }
25259    }
25260
25261    /**
25262     * <p>
25263     * This class represents a delegate that can be registered in a {@link View}
25264     * to enhance accessibility support via composition rather via inheritance.
25265     * It is specifically targeted to widget developers that extend basic View
25266     * classes i.e. classes in package android.view, that would like their
25267     * applications to be backwards compatible.
25268     * </p>
25269     * <div class="special reference">
25270     * <h3>Developer Guides</h3>
25271     * <p>For more information about making applications accessible, read the
25272     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
25273     * developer guide.</p>
25274     * </div>
25275     * <p>
25276     * A scenario in which a developer would like to use an accessibility delegate
25277     * is overriding a method introduced in a later API version than the minimal API
25278     * version supported by the application. For example, the method
25279     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
25280     * in API version 4 when the accessibility APIs were first introduced. If a
25281     * developer would like his application to run on API version 4 devices (assuming
25282     * all other APIs used by the application are version 4 or lower) and take advantage
25283     * of this method, instead of overriding the method which would break the application's
25284     * backwards compatibility, he can override the corresponding method in this
25285     * delegate and register the delegate in the target View if the API version of
25286     * the system is high enough, i.e. the API version is the same as or higher than the API
25287     * version that introduced
25288     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
25289     * </p>
25290     * <p>
25291     * Here is an example implementation:
25292     * </p>
25293     * <code><pre><p>
25294     * if (Build.VERSION.SDK_INT >= 14) {
25295     *     // If the API version is equal of higher than the version in
25296     *     // which onInitializeAccessibilityNodeInfo was introduced we
25297     *     // register a delegate with a customized implementation.
25298     *     View view = findViewById(R.id.view_id);
25299     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
25300     *         public void onInitializeAccessibilityNodeInfo(View host,
25301     *                 AccessibilityNodeInfo info) {
25302     *             // Let the default implementation populate the info.
25303     *             super.onInitializeAccessibilityNodeInfo(host, info);
25304     *             // Set some other information.
25305     *             info.setEnabled(host.isEnabled());
25306     *         }
25307     *     });
25308     * }
25309     * </code></pre></p>
25310     * <p>
25311     * This delegate contains methods that correspond to the accessibility methods
25312     * in View. If a delegate has been specified the implementation in View hands
25313     * off handling to the corresponding method in this delegate. The default
25314     * implementation the delegate methods behaves exactly as the corresponding
25315     * method in View for the case of no accessibility delegate been set. Hence,
25316     * to customize the behavior of a View method, clients can override only the
25317     * corresponding delegate method without altering the behavior of the rest
25318     * accessibility related methods of the host view.
25319     * </p>
25320     * <p>
25321     * <strong>Note:</strong> On platform versions prior to
25322     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
25323     * views in the {@code android.widget.*} package are called <i>before</i>
25324     * host methods. This prevents certain properties such as class name from
25325     * being modified by overriding
25326     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
25327     * as any changes will be overwritten by the host class.
25328     * <p>
25329     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
25330     * methods are called <i>after</i> host methods, which all properties to be
25331     * modified without being overwritten by the host class.
25332     */
25333    public static class AccessibilityDelegate {
25334
25335        /**
25336         * Sends an accessibility event of the given type. If accessibility is not
25337         * enabled this method has no effect.
25338         * <p>
25339         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
25340         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
25341         * been set.
25342         * </p>
25343         *
25344         * @param host The View hosting the delegate.
25345         * @param eventType The type of the event to send.
25346         *
25347         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25348         */
25349        public void sendAccessibilityEvent(View host, int eventType) {
25350            host.sendAccessibilityEventInternal(eventType);
25351        }
25352
25353        /**
25354         * Performs the specified accessibility action on the view. For
25355         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25356         * <p>
25357         * The default implementation behaves as
25358         * {@link View#performAccessibilityAction(int, Bundle)
25359         *  View#performAccessibilityAction(int, Bundle)} for the case of
25360         *  no accessibility delegate been set.
25361         * </p>
25362         *
25363         * @param action The action to perform.
25364         * @return Whether the action was performed.
25365         *
25366         * @see View#performAccessibilityAction(int, Bundle)
25367         *      View#performAccessibilityAction(int, Bundle)
25368         */
25369        public boolean performAccessibilityAction(View host, int action, Bundle args) {
25370            return host.performAccessibilityActionInternal(action, args);
25371        }
25372
25373        /**
25374         * Sends an accessibility event. This method behaves exactly as
25375         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25376         * empty {@link AccessibilityEvent} and does not perform a check whether
25377         * accessibility is enabled.
25378         * <p>
25379         * The default implementation behaves as
25380         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25381         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25382         * the case of no accessibility delegate been set.
25383         * </p>
25384         *
25385         * @param host The View hosting the delegate.
25386         * @param event The event to send.
25387         *
25388         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25389         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25390         */
25391        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25392            host.sendAccessibilityEventUncheckedInternal(event);
25393        }
25394
25395        /**
25396         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25397         * to its children for adding their text content to the event.
25398         * <p>
25399         * The default implementation behaves as
25400         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25401         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25402         * the case of no accessibility delegate been set.
25403         * </p>
25404         *
25405         * @param host The View hosting the delegate.
25406         * @param event The event.
25407         * @return True if the event population was completed.
25408         *
25409         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25410         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25411         */
25412        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25413            return host.dispatchPopulateAccessibilityEventInternal(event);
25414        }
25415
25416        /**
25417         * Gives a chance to the host View to populate the accessibility event with its
25418         * text content.
25419         * <p>
25420         * The default implementation behaves as
25421         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25422         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25423         * the case of no accessibility delegate been set.
25424         * </p>
25425         *
25426         * @param host The View hosting the delegate.
25427         * @param event The accessibility event which to populate.
25428         *
25429         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25430         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25431         */
25432        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25433            host.onPopulateAccessibilityEventInternal(event);
25434        }
25435
25436        /**
25437         * Initializes an {@link AccessibilityEvent} with information about the
25438         * the host View which is the event source.
25439         * <p>
25440         * The default implementation behaves as
25441         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25442         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25443         * the case of no accessibility delegate been set.
25444         * </p>
25445         *
25446         * @param host The View hosting the delegate.
25447         * @param event The event to initialize.
25448         *
25449         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25450         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25451         */
25452        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25453            host.onInitializeAccessibilityEventInternal(event);
25454        }
25455
25456        /**
25457         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25458         * <p>
25459         * The default implementation behaves as
25460         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25461         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25462         * the case of no accessibility delegate been set.
25463         * </p>
25464         *
25465         * @param host The View hosting the delegate.
25466         * @param info The instance to initialize.
25467         *
25468         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25469         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25470         */
25471        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25472            host.onInitializeAccessibilityNodeInfoInternal(info);
25473        }
25474
25475        /**
25476         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25477         * additional data.
25478         * <p>
25479         * This method only needs to be implemented if the View offers to provide additional data.
25480         * </p>
25481         * <p>
25482         * The default implementation behaves as
25483         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, int) for
25484         * the case where no accessibility delegate is set.
25485         * </p>
25486         *
25487         * @param host The View hosting the delegate. Never {@code null}.
25488         * @param info The info to which to add the extra data. Never {@code null}.
25489         * @param extraDataKey A key specifying the type of extra data to add to the info. The
25490         *                     extra data should be added to the {@link Bundle} returned by
25491         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25492         *                     {@code null}.
25493         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25494         *                  May be {@code null} if the if the service provided no arguments.
25495         *
25496         * @see AccessibilityNodeInfo#setExtraAvailableData
25497         */
25498        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25499                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25500                @Nullable Bundle arguments) {
25501            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25502        }
25503
25504        /**
25505         * Called when a child of the host View has requested sending an
25506         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25507         * to augment the event.
25508         * <p>
25509         * The default implementation behaves as
25510         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25511         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
25512         * the case of no accessibility delegate been set.
25513         * </p>
25514         *
25515         * @param host The View hosting the delegate.
25516         * @param child The child which requests sending the event.
25517         * @param event The event to be sent.
25518         * @return True if the event should be sent
25519         *
25520         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25521         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25522         */
25523        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
25524                AccessibilityEvent event) {
25525            return host.onRequestSendAccessibilityEventInternal(child, event);
25526        }
25527
25528        /**
25529         * Gets the provider for managing a virtual view hierarchy rooted at this View
25530         * and reported to {@link android.accessibilityservice.AccessibilityService}s
25531         * that explore the window content.
25532         * <p>
25533         * The default implementation behaves as
25534         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
25535         * the case of no accessibility delegate been set.
25536         * </p>
25537         *
25538         * @return The provider.
25539         *
25540         * @see AccessibilityNodeProvider
25541         */
25542        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
25543            return null;
25544        }
25545
25546        /**
25547         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
25548         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
25549         * This method is responsible for obtaining an accessibility node info from a
25550         * pool of reusable instances and calling
25551         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
25552         * view to initialize the former.
25553         * <p>
25554         * <strong>Note:</strong> The client is responsible for recycling the obtained
25555         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
25556         * creation.
25557         * </p>
25558         * <p>
25559         * The default implementation behaves as
25560         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
25561         * the case of no accessibility delegate been set.
25562         * </p>
25563         * @return A populated {@link AccessibilityNodeInfo}.
25564         *
25565         * @see AccessibilityNodeInfo
25566         *
25567         * @hide
25568         */
25569        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
25570            return host.createAccessibilityNodeInfoInternal();
25571        }
25572    }
25573
25574    private static class MatchIdPredicate implements Predicate<View> {
25575        public int mId;
25576
25577        @Override
25578        public boolean test(View view) {
25579            return (view.mID == mId);
25580        }
25581    }
25582
25583    private static class MatchLabelForPredicate implements Predicate<View> {
25584        private int mLabeledId;
25585
25586        @Override
25587        public boolean test(View view) {
25588            return (view.mLabelForId == mLabeledId);
25589        }
25590    }
25591
25592    private class SendViewStateChangedAccessibilityEvent implements Runnable {
25593        private int mChangeTypes = 0;
25594        private boolean mPosted;
25595        private boolean mPostedWithDelay;
25596        private long mLastEventTimeMillis;
25597
25598        @Override
25599        public void run() {
25600            mPosted = false;
25601            mPostedWithDelay = false;
25602            mLastEventTimeMillis = SystemClock.uptimeMillis();
25603            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
25604                final AccessibilityEvent event = AccessibilityEvent.obtain();
25605                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
25606                event.setContentChangeTypes(mChangeTypes);
25607                sendAccessibilityEventUnchecked(event);
25608            }
25609            mChangeTypes = 0;
25610        }
25611
25612        public void runOrPost(int changeType) {
25613            mChangeTypes |= changeType;
25614
25615            // If this is a live region or the child of a live region, collect
25616            // all events from this frame and send them on the next frame.
25617            if (inLiveRegion()) {
25618                // If we're already posted with a delay, remove that.
25619                if (mPostedWithDelay) {
25620                    removeCallbacks(this);
25621                    mPostedWithDelay = false;
25622                }
25623                // Only post if we're not already posted.
25624                if (!mPosted) {
25625                    post(this);
25626                    mPosted = true;
25627                }
25628                return;
25629            }
25630
25631            if (mPosted) {
25632                return;
25633            }
25634
25635            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
25636            final long minEventIntevalMillis =
25637                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
25638            if (timeSinceLastMillis >= minEventIntevalMillis) {
25639                removeCallbacks(this);
25640                run();
25641            } else {
25642                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
25643                mPostedWithDelay = true;
25644            }
25645        }
25646    }
25647
25648    private boolean inLiveRegion() {
25649        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25650            return true;
25651        }
25652
25653        ViewParent parent = getParent();
25654        while (parent instanceof View) {
25655            if (((View) parent).getAccessibilityLiveRegion()
25656                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
25657                return true;
25658            }
25659            parent = parent.getParent();
25660        }
25661
25662        return false;
25663    }
25664
25665    /**
25666     * Dump all private flags in readable format, useful for documentation and
25667     * sanity checking.
25668     */
25669    private static void dumpFlags() {
25670        final HashMap<String, String> found = Maps.newHashMap();
25671        try {
25672            for (Field field : View.class.getDeclaredFields()) {
25673                final int modifiers = field.getModifiers();
25674                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
25675                    if (field.getType().equals(int.class)) {
25676                        final int value = field.getInt(null);
25677                        dumpFlag(found, field.getName(), value);
25678                    } else if (field.getType().equals(int[].class)) {
25679                        final int[] values = (int[]) field.get(null);
25680                        for (int i = 0; i < values.length; i++) {
25681                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
25682                        }
25683                    }
25684                }
25685            }
25686        } catch (IllegalAccessException e) {
25687            throw new RuntimeException(e);
25688        }
25689
25690        final ArrayList<String> keys = Lists.newArrayList();
25691        keys.addAll(found.keySet());
25692        Collections.sort(keys);
25693        for (String key : keys) {
25694            Log.d(VIEW_LOG_TAG, found.get(key));
25695        }
25696    }
25697
25698    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
25699        // Sort flags by prefix, then by bits, always keeping unique keys
25700        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
25701        final int prefix = name.indexOf('_');
25702        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
25703        final String output = bits + " " + name;
25704        found.put(key, output);
25705    }
25706
25707    /** {@hide} */
25708    public void encode(@NonNull ViewHierarchyEncoder stream) {
25709        stream.beginObject(this);
25710        encodeProperties(stream);
25711        stream.endObject();
25712    }
25713
25714    /** {@hide} */
25715    @CallSuper
25716    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
25717        Object resolveId = ViewDebug.resolveId(getContext(), mID);
25718        if (resolveId instanceof String) {
25719            stream.addProperty("id", (String) resolveId);
25720        } else {
25721            stream.addProperty("id", mID);
25722        }
25723
25724        stream.addProperty("misc:transformation.alpha",
25725                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
25726        stream.addProperty("misc:transitionName", getTransitionName());
25727
25728        // layout
25729        stream.addProperty("layout:left", mLeft);
25730        stream.addProperty("layout:right", mRight);
25731        stream.addProperty("layout:top", mTop);
25732        stream.addProperty("layout:bottom", mBottom);
25733        stream.addProperty("layout:width", getWidth());
25734        stream.addProperty("layout:height", getHeight());
25735        stream.addProperty("layout:layoutDirection", getLayoutDirection());
25736        stream.addProperty("layout:layoutRtl", isLayoutRtl());
25737        stream.addProperty("layout:hasTransientState", hasTransientState());
25738        stream.addProperty("layout:baseline", getBaseline());
25739
25740        // layout params
25741        ViewGroup.LayoutParams layoutParams = getLayoutParams();
25742        if (layoutParams != null) {
25743            stream.addPropertyKey("layoutParams");
25744            layoutParams.encode(stream);
25745        }
25746
25747        // scrolling
25748        stream.addProperty("scrolling:scrollX", mScrollX);
25749        stream.addProperty("scrolling:scrollY", mScrollY);
25750
25751        // padding
25752        stream.addProperty("padding:paddingLeft", mPaddingLeft);
25753        stream.addProperty("padding:paddingRight", mPaddingRight);
25754        stream.addProperty("padding:paddingTop", mPaddingTop);
25755        stream.addProperty("padding:paddingBottom", mPaddingBottom);
25756        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
25757        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
25758        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
25759        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
25760        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
25761
25762        // measurement
25763        stream.addProperty("measurement:minHeight", mMinHeight);
25764        stream.addProperty("measurement:minWidth", mMinWidth);
25765        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
25766        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
25767
25768        // drawing
25769        stream.addProperty("drawing:elevation", getElevation());
25770        stream.addProperty("drawing:translationX", getTranslationX());
25771        stream.addProperty("drawing:translationY", getTranslationY());
25772        stream.addProperty("drawing:translationZ", getTranslationZ());
25773        stream.addProperty("drawing:rotation", getRotation());
25774        stream.addProperty("drawing:rotationX", getRotationX());
25775        stream.addProperty("drawing:rotationY", getRotationY());
25776        stream.addProperty("drawing:scaleX", getScaleX());
25777        stream.addProperty("drawing:scaleY", getScaleY());
25778        stream.addProperty("drawing:pivotX", getPivotX());
25779        stream.addProperty("drawing:pivotY", getPivotY());
25780        stream.addProperty("drawing:opaque", isOpaque());
25781        stream.addProperty("drawing:alpha", getAlpha());
25782        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
25783        stream.addProperty("drawing:shadow", hasShadow());
25784        stream.addProperty("drawing:solidColor", getSolidColor());
25785        stream.addProperty("drawing:layerType", mLayerType);
25786        stream.addProperty("drawing:willNotDraw", willNotDraw());
25787        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
25788        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
25789        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
25790        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
25791
25792        // focus
25793        stream.addProperty("focus:hasFocus", hasFocus());
25794        stream.addProperty("focus:isFocused", isFocused());
25795        stream.addProperty("focus:focusable", getFocusable());
25796        stream.addProperty("focus:isFocusable", isFocusable());
25797        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
25798
25799        stream.addProperty("misc:clickable", isClickable());
25800        stream.addProperty("misc:pressed", isPressed());
25801        stream.addProperty("misc:selected", isSelected());
25802        stream.addProperty("misc:touchMode", isInTouchMode());
25803        stream.addProperty("misc:hovered", isHovered());
25804        stream.addProperty("misc:activated", isActivated());
25805
25806        stream.addProperty("misc:visibility", getVisibility());
25807        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
25808        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
25809
25810        stream.addProperty("misc:enabled", isEnabled());
25811        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
25812        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
25813
25814        // theme attributes
25815        Resources.Theme theme = getContext().getTheme();
25816        if (theme != null) {
25817            stream.addPropertyKey("theme");
25818            theme.encode(stream);
25819        }
25820
25821        // view attribute information
25822        int n = mAttributes != null ? mAttributes.length : 0;
25823        stream.addProperty("meta:__attrCount__", n/2);
25824        for (int i = 0; i < n; i += 2) {
25825            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
25826        }
25827
25828        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
25829
25830        // text
25831        stream.addProperty("text:textDirection", getTextDirection());
25832        stream.addProperty("text:textAlignment", getTextAlignment());
25833
25834        // accessibility
25835        CharSequence contentDescription = getContentDescription();
25836        stream.addProperty("accessibility:contentDescription",
25837                contentDescription == null ? "" : contentDescription.toString());
25838        stream.addProperty("accessibility:labelFor", getLabelFor());
25839        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
25840    }
25841
25842    /**
25843     * Determine if this view is rendered on a round wearable device and is the main view
25844     * on the screen.
25845     */
25846    boolean shouldDrawRoundScrollbar() {
25847        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
25848            return false;
25849        }
25850
25851        final View rootView = getRootView();
25852        final WindowInsets insets = getRootWindowInsets();
25853
25854        int height = getHeight();
25855        int width = getWidth();
25856        int displayHeight = rootView.getHeight();
25857        int displayWidth = rootView.getWidth();
25858
25859        if (height != displayHeight || width != displayWidth) {
25860            return false;
25861        }
25862
25863        getLocationInWindow(mAttachInfo.mTmpLocation);
25864        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
25865                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
25866    }
25867
25868    /**
25869     * Sets the tooltip text which will be displayed in a small popup next to the view.
25870     * <p>
25871     * The tooltip will be displayed:
25872     * <ul>
25873     * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
25874     * menu). </li>
25875     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
25876     * </ul>
25877     * <p>
25878     * <strong>Note:</strong> Do not override this method, as it will have no
25879     * effect on the text displayed in the tooltip.
25880     *
25881     * @param tooltipText the tooltip text, or null if no tooltip is required
25882     * @see #getTooltipText()
25883     * @attr ref android.R.styleable#View_tooltipText
25884     */
25885    public void setTooltipText(@Nullable CharSequence tooltipText) {
25886        if (TextUtils.isEmpty(tooltipText)) {
25887            setFlags(0, TOOLTIP);
25888            hideTooltip();
25889            mTooltipInfo = null;
25890        } else {
25891            setFlags(TOOLTIP, TOOLTIP);
25892            if (mTooltipInfo == null) {
25893                mTooltipInfo = new TooltipInfo();
25894                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
25895                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
25896            }
25897            mTooltipInfo.mTooltipText = tooltipText;
25898            if (mTooltipInfo.mTooltipPopup != null && mTooltipInfo.mTooltipPopup.isShowing()) {
25899                mTooltipInfo.mTooltipPopup.updateContent(mTooltipInfo.mTooltipText);
25900            }
25901        }
25902    }
25903
25904    /**
25905     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25906     */
25907    public void setTooltip(@Nullable CharSequence tooltipText) {
25908        setTooltipText(tooltipText);
25909    }
25910
25911    /**
25912     * Returns the view's tooltip text.
25913     *
25914     * <strong>Note:</strong> Do not override this method, as it will have no
25915     * effect on the text displayed in the tooltip. You must call
25916     * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
25917     *
25918     * @return the tooltip text
25919     * @see #setTooltipText(CharSequence)
25920     * @attr ref android.R.styleable#View_tooltipText
25921     */
25922    @Nullable
25923    public CharSequence getTooltipText() {
25924        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
25925    }
25926
25927    /**
25928     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
25929     */
25930    @Nullable
25931    public CharSequence getTooltip() {
25932        return getTooltipText();
25933    }
25934
25935    private boolean showTooltip(int x, int y, boolean fromLongClick) {
25936        if (mAttachInfo == null || mTooltipInfo == null) {
25937            return false;
25938        }
25939        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
25940            return false;
25941        }
25942        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
25943            return false;
25944        }
25945        hideTooltip();
25946        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
25947        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
25948        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
25949        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
25950        mAttachInfo.mTooltipHost = this;
25951        return true;
25952    }
25953
25954    void hideTooltip() {
25955        if (mTooltipInfo == null) {
25956            return;
25957        }
25958        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25959        if (mTooltipInfo.mTooltipPopup == null) {
25960            return;
25961        }
25962        mTooltipInfo.mTooltipPopup.hide();
25963        mTooltipInfo.mTooltipPopup = null;
25964        mTooltipInfo.mTooltipFromLongClick = false;
25965        if (mAttachInfo != null) {
25966            mAttachInfo.mTooltipHost = null;
25967        }
25968    }
25969
25970    private boolean showLongClickTooltip(int x, int y) {
25971        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25972        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
25973        return showTooltip(x, y, true);
25974    }
25975
25976    private void showHoverTooltip() {
25977        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
25978    }
25979
25980    boolean dispatchTooltipHoverEvent(MotionEvent event) {
25981        if (mTooltipInfo == null) {
25982            return false;
25983        }
25984        switch(event.getAction()) {
25985            case MotionEvent.ACTION_HOVER_MOVE:
25986                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
25987                    break;
25988                }
25989                if (!mTooltipInfo.mTooltipFromLongClick) {
25990                    if (mTooltipInfo.mTooltipPopup == null) {
25991                        // Schedule showing the tooltip after a timeout.
25992                        mTooltipInfo.mAnchorX = (int) event.getX();
25993                        mTooltipInfo.mAnchorY = (int) event.getY();
25994                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
25995                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
25996                                ViewConfiguration.getHoverTooltipShowTimeout());
25997                    }
25998
25999                    // Hide hover-triggered tooltip after a period of inactivity.
26000                    // Match the timeout used by NativeInputManager to hide the mouse pointer
26001                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
26002                    final int timeout;
26003                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
26004                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
26005                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
26006                    } else {
26007                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
26008                    }
26009                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26010                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
26011                }
26012                return true;
26013
26014            case MotionEvent.ACTION_HOVER_EXIT:
26015                if (!mTooltipInfo.mTooltipFromLongClick) {
26016                    hideTooltip();
26017                }
26018                break;
26019        }
26020        return false;
26021    }
26022
26023    void handleTooltipKey(KeyEvent event) {
26024        switch (event.getAction()) {
26025            case KeyEvent.ACTION_DOWN:
26026                if (event.getRepeatCount() == 0) {
26027                    hideTooltip();
26028                }
26029                break;
26030
26031            case KeyEvent.ACTION_UP:
26032                handleTooltipUp();
26033                break;
26034        }
26035    }
26036
26037    private void handleTooltipUp() {
26038        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26039            return;
26040        }
26041        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26042        postDelayed(mTooltipInfo.mHideTooltipRunnable,
26043                ViewConfiguration.getLongPressTooltipHideTimeout());
26044    }
26045
26046    private int getFocusableAttribute(TypedArray attributes) {
26047        TypedValue val = new TypedValue();
26048        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
26049            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
26050                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
26051            } else {
26052                return val.data;
26053            }
26054        } else {
26055            return FOCUSABLE_AUTO;
26056        }
26057    }
26058
26059    /**
26060     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
26061     * is not showing.
26062     * @hide
26063     */
26064    @TestApi
26065    public View getTooltipView() {
26066        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26067            return null;
26068        }
26069        return mTooltipInfo.mTooltipPopup.getContentView();
26070    }
26071}
26072