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.AutofillId;
104import android.view.autofill.AutofillManager;
105import android.view.autofill.AutofillValue;
106import android.view.inputmethod.EditorInfo;
107import android.view.inputmethod.InputConnection;
108import android.view.inputmethod.InputMethodManager;
109import android.widget.Checkable;
110import android.widget.FrameLayout;
111import android.widget.ScrollBarDrawable;
112
113import com.android.internal.R;
114import com.android.internal.view.TooltipPopup;
115import com.android.internal.view.menu.MenuBuilder;
116import com.android.internal.widget.ScrollBarUtils;
117
118import com.google.android.collect.Lists;
119import com.google.android.collect.Maps;
120
121import java.lang.annotation.Retention;
122import java.lang.annotation.RetentionPolicy;
123import java.lang.ref.WeakReference;
124import java.lang.reflect.Field;
125import java.lang.reflect.InvocationTargetException;
126import java.lang.reflect.Method;
127import java.lang.reflect.Modifier;
128import java.util.ArrayList;
129import java.util.Arrays;
130import java.util.Calendar;
131import java.util.Collection;
132import java.util.Collections;
133import java.util.HashMap;
134import java.util.List;
135import java.util.Locale;
136import java.util.Map;
137import java.util.concurrent.CopyOnWriteArrayList;
138import java.util.concurrent.atomic.AtomicInteger;
139import java.util.function.Predicate;
140
141/**
142 * <p>
143 * This class represents the basic building block for user interface components. A View
144 * occupies a rectangular area on the screen and is responsible for drawing and
145 * event handling. View is the base class for <em>widgets</em>, which are
146 * used to create interactive UI components (buttons, text fields, etc.). The
147 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
148 * are invisible containers that hold other Views (or other ViewGroups) and define
149 * their layout properties.
150 * </p>
151 *
152 * <div class="special reference">
153 * <h3>Developer Guides</h3>
154 * <p>For information about using this class to develop your application's user interface,
155 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
156 * </div>
157 *
158 * <a name="Using"></a>
159 * <h3>Using Views</h3>
160 * <p>
161 * All of the views in a window are arranged in a single tree. You can add views
162 * either from code or by specifying a tree of views in one or more XML layout
163 * files. There are many specialized subclasses of views that act as controls or
164 * are capable of displaying text, images, or other content.
165 * </p>
166 * <p>
167 * Once you have created a tree of views, there are typically a few types of
168 * common operations you may wish to perform:
169 * <ul>
170 * <li><strong>Set properties:</strong> for example setting the text of a
171 * {@link android.widget.TextView}. The available properties and the methods
172 * that set them will vary among the different subclasses of views. Note that
173 * properties that are known at build time can be set in the XML layout
174 * files.</li>
175 * <li><strong>Set focus:</strong> The framework will handle moving focus in
176 * response to user input. To force focus to a specific view, call
177 * {@link #requestFocus}.</li>
178 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
179 * that will be notified when something interesting happens to the view. For
180 * example, all views will let you set a listener to be notified when the view
181 * gains or loses focus. You can register such a listener using
182 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
183 * Other view subclasses offer more specialized listeners. For example, a Button
184 * exposes a listener to notify clients when the button is clicked.</li>
185 * <li><strong>Set visibility:</strong> You can hide or show views using
186 * {@link #setVisibility(int)}.</li>
187 * </ul>
188 * </p>
189 * <p><em>
190 * Note: The Android framework is responsible for measuring, laying out and
191 * drawing views. You should not call methods that perform these actions on
192 * views yourself unless you are actually implementing a
193 * {@link android.view.ViewGroup}.
194 * </em></p>
195 *
196 * <a name="Lifecycle"></a>
197 * <h3>Implementing a Custom View</h3>
198 *
199 * <p>
200 * To implement a custom view, you will usually begin by providing overrides for
201 * some of the standard methods that the framework calls on all views. You do
202 * not need to override all of these methods. In fact, you can start by just
203 * overriding {@link #onDraw(android.graphics.Canvas)}.
204 * <table border="2" width="85%" align="center" cellpadding="5">
205 *     <thead>
206 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
207 *     </thead>
208 *
209 *     <tbody>
210 *     <tr>
211 *         <td rowspan="2">Creation</td>
212 *         <td>Constructors</td>
213 *         <td>There is a form of the constructor that are called when the view
214 *         is created from code and a form that is called when the view is
215 *         inflated from a layout file. The second form should parse and apply
216 *         any attributes defined in the layout file.
217 *         </td>
218 *     </tr>
219 *     <tr>
220 *         <td><code>{@link #onFinishInflate()}</code></td>
221 *         <td>Called after a view and all of its children has been inflated
222 *         from XML.</td>
223 *     </tr>
224 *
225 *     <tr>
226 *         <td rowspan="3">Layout</td>
227 *         <td><code>{@link #onMeasure(int, int)}</code></td>
228 *         <td>Called to determine the size requirements for this view and all
229 *         of its children.
230 *         </td>
231 *     </tr>
232 *     <tr>
233 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
234 *         <td>Called when this view should assign a size and position to all
235 *         of its children.
236 *         </td>
237 *     </tr>
238 *     <tr>
239 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
240 *         <td>Called when the size of this view has changed.
241 *         </td>
242 *     </tr>
243 *
244 *     <tr>
245 *         <td>Drawing</td>
246 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
247 *         <td>Called when the view should render its content.
248 *         </td>
249 *     </tr>
250 *
251 *     <tr>
252 *         <td rowspan="4">Event processing</td>
253 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
254 *         <td>Called when a new hardware key event occurs.
255 *         </td>
256 *     </tr>
257 *     <tr>
258 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
259 *         <td>Called when a hardware key up event occurs.
260 *         </td>
261 *     </tr>
262 *     <tr>
263 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
264 *         <td>Called when a trackball motion event occurs.
265 *         </td>
266 *     </tr>
267 *     <tr>
268 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
269 *         <td>Called when a touch screen motion event occurs.
270 *         </td>
271 *     </tr>
272 *
273 *     <tr>
274 *         <td rowspan="2">Focus</td>
275 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
276 *         <td>Called when the view gains or loses focus.
277 *         </td>
278 *     </tr>
279 *
280 *     <tr>
281 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
282 *         <td>Called when the window containing the view gains or loses focus.
283 *         </td>
284 *     </tr>
285 *
286 *     <tr>
287 *         <td rowspan="3">Attaching</td>
288 *         <td><code>{@link #onAttachedToWindow()}</code></td>
289 *         <td>Called when the view is attached to a window.
290 *         </td>
291 *     </tr>
292 *
293 *     <tr>
294 *         <td><code>{@link #onDetachedFromWindow}</code></td>
295 *         <td>Called when the view is detached from its window.
296 *         </td>
297 *     </tr>
298 *
299 *     <tr>
300 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
301 *         <td>Called when the visibility of the window containing the view
302 *         has changed.
303 *         </td>
304 *     </tr>
305 *     </tbody>
306 *
307 * </table>
308 * </p>
309 *
310 * <a name="IDs"></a>
311 * <h3>IDs</h3>
312 * Views may have an integer id associated with them. These ids are typically
313 * assigned in the layout XML files, and are used to find specific views within
314 * the view tree. A common pattern is to:
315 * <ul>
316 * <li>Define a Button in the layout file and assign it a unique ID.
317 * <pre>
318 * &lt;Button
319 *     android:id="@+id/my_button"
320 *     android:layout_width="wrap_content"
321 *     android:layout_height="wrap_content"
322 *     android:text="@string/my_button_text"/&gt;
323 * </pre></li>
324 * <li>From the onCreate method of an Activity, find the Button
325 * <pre class="prettyprint">
326 *      Button myButton = findViewById(R.id.my_button);
327 * </pre></li>
328 * </ul>
329 * <p>
330 * View IDs need not be unique throughout the tree, but it is good practice to
331 * ensure that they are at least unique within the part of the tree you are
332 * searching.
333 * </p>
334 *
335 * <a name="Position"></a>
336 * <h3>Position</h3>
337 * <p>
338 * The geometry of a view is that of a rectangle. A view has a location,
339 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
340 * two dimensions, expressed as a width and a height. The unit for location
341 * and dimensions is the pixel.
342 * </p>
343 *
344 * <p>
345 * It is possible to retrieve the location of a view by invoking the methods
346 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
347 * coordinate of the rectangle representing the view. The latter returns the
348 * top, or Y, coordinate of the rectangle representing the view. These methods
349 * both return the location of the view relative to its parent. For instance,
350 * when getLeft() returns 20, that means the view is located 20 pixels to the
351 * right of the left edge of its direct parent.
352 * </p>
353 *
354 * <p>
355 * In addition, several convenience methods are offered to avoid unnecessary
356 * computations, namely {@link #getRight()} and {@link #getBottom()}.
357 * These methods return the coordinates of the right and bottom edges of the
358 * rectangle representing the view. For instance, calling {@link #getRight()}
359 * is similar to the following computation: <code>getLeft() + getWidth()</code>
360 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
361 * </p>
362 *
363 * <a name="SizePaddingMargins"></a>
364 * <h3>Size, padding and margins</h3>
365 * <p>
366 * The size of a view is expressed with a width and a height. A view actually
367 * possess two pairs of width and height values.
368 * </p>
369 *
370 * <p>
371 * The first pair is known as <em>measured width</em> and
372 * <em>measured height</em>. These dimensions define how big a view wants to be
373 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
374 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
375 * and {@link #getMeasuredHeight()}.
376 * </p>
377 *
378 * <p>
379 * The second pair is simply known as <em>width</em> and <em>height</em>, or
380 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
381 * dimensions define the actual size of the view on screen, at drawing time and
382 * after layout. These values may, but do not have to, be different from the
383 * measured width and height. The width and height can be obtained by calling
384 * {@link #getWidth()} and {@link #getHeight()}.
385 * </p>
386 *
387 * <p>
388 * To measure its dimensions, a view takes into account its padding. The padding
389 * is expressed in pixels for the left, top, right and bottom parts of the view.
390 * Padding can be used to offset the content of the view by a specific amount of
391 * pixels. For instance, a left padding of 2 will push the view's content by
392 * 2 pixels to the right of the left edge. Padding can be set using the
393 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
394 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
395 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
396 * {@link #getPaddingEnd()}.
397 * </p>
398 *
399 * <p>
400 * Even though a view can define a padding, it does not provide any support for
401 * margins. However, view groups provide such a support. Refer to
402 * {@link android.view.ViewGroup} and
403 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
404 * </p>
405 *
406 * <a name="Layout"></a>
407 * <h3>Layout</h3>
408 * <p>
409 * Layout is a two pass process: a measure pass and a layout pass. The measuring
410 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
411 * of the view tree. Each view pushes dimension specifications down the tree
412 * during the recursion. At the end of the measure pass, every view has stored
413 * its measurements. The second pass happens in
414 * {@link #layout(int,int,int,int)} and is also top-down. During
415 * this pass each parent is responsible for positioning all of its children
416 * using the sizes computed in the measure pass.
417 * </p>
418 *
419 * <p>
420 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
421 * {@link #getMeasuredHeight()} values must be set, along with those for all of
422 * that view's descendants. A view's measured width and measured height values
423 * must respect the constraints imposed by the view's parents. This guarantees
424 * that at the end of the measure pass, all parents accept all of their
425 * children's measurements. A parent view may call measure() more than once on
426 * its children. For example, the parent may measure each child once with
427 * unspecified dimensions to find out how big they want to be, then call
428 * measure() on them again with actual numbers if the sum of all the children's
429 * unconstrained sizes is too big or too small.
430 * </p>
431 *
432 * <p>
433 * The measure pass uses two classes to communicate dimensions. The
434 * {@link MeasureSpec} class is used by views to tell their parents how they
435 * want to be measured and positioned. The base LayoutParams class just
436 * describes how big the view wants to be for both width and height. For each
437 * dimension, it can specify one of:
438 * <ul>
439 * <li> an exact number
440 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
441 * (minus padding)
442 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
443 * enclose its content (plus padding).
444 * </ul>
445 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
446 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
447 * an X and Y value.
448 * </p>
449 *
450 * <p>
451 * MeasureSpecs are used to push requirements down the tree from parent to
452 * child. A MeasureSpec can be in one of three modes:
453 * <ul>
454 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
455 * of a child view. For example, a LinearLayout may call measure() on its child
456 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
457 * tall the child view wants to be given a width of 240 pixels.
458 * <li>EXACTLY: This is used by the parent to impose an exact size on the
459 * child. The child must use this size, and guarantee that all of its
460 * descendants will fit within this size.
461 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
462 * child. The child must guarantee that it and all of its descendants will fit
463 * within this size.
464 * </ul>
465 * </p>
466 *
467 * <p>
468 * To initiate a layout, call {@link #requestLayout}. This method is typically
469 * called by a view on itself when it believes that is can no longer fit within
470 * its current bounds.
471 * </p>
472 *
473 * <a name="Drawing"></a>
474 * <h3>Drawing</h3>
475 * <p>
476 * Drawing is handled by walking the tree and recording the drawing commands of
477 * any View that needs to update. After this, the drawing commands of the
478 * entire tree are issued to screen, clipped to the newly damaged area.
479 * </p>
480 *
481 * <p>
482 * The tree is largely recorded and drawn in order, with parents drawn before
483 * (i.e., behind) their children, with siblings drawn in the order they appear
484 * in the tree. If you set a background drawable for a View, then the View will
485 * draw it before calling back to its <code>onDraw()</code> method. The child
486 * drawing order can be overridden with
487 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
488 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
489 * </p>
490 *
491 * <p>
492 * To force a view to draw, call {@link #invalidate()}.
493 * </p>
494 *
495 * <a name="EventHandlingThreading"></a>
496 * <h3>Event Handling and Threading</h3>
497 * <p>
498 * The basic cycle of a view is as follows:
499 * <ol>
500 * <li>An event comes in and is dispatched to the appropriate view. The view
501 * handles the event and notifies any listeners.</li>
502 * <li>If in the course of processing the event, the view's bounds may need
503 * to be changed, the view will call {@link #requestLayout()}.</li>
504 * <li>Similarly, if in the course of processing the event the view's appearance
505 * may need to be changed, the view will call {@link #invalidate()}.</li>
506 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
507 * the framework will take care of measuring, laying out, and drawing the tree
508 * as appropriate.</li>
509 * </ol>
510 * </p>
511 *
512 * <p><em>Note: The entire view tree is single threaded. You must always be on
513 * the UI thread when calling any method on any view.</em>
514 * If you are doing work on other threads and want to update the state of a view
515 * from that thread, you should use a {@link Handler}.
516 * </p>
517 *
518 * <a name="FocusHandling"></a>
519 * <h3>Focus Handling</h3>
520 * <p>
521 * The framework will handle routine focus movement in response to user input.
522 * This includes changing the focus as views are removed or hidden, or as new
523 * views become available. Views indicate their willingness to take focus
524 * through the {@link #isFocusable} method. To change whether a view can take
525 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
526 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
527 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
528 * </p>
529 * <p>
530 * Focus movement is based on an algorithm which finds the nearest neighbor in a
531 * given direction. In rare cases, the default algorithm may not match the
532 * intended behavior of the developer. In these situations, you can provide
533 * explicit overrides by using these XML attributes in the layout file:
534 * <pre>
535 * nextFocusDown
536 * nextFocusLeft
537 * nextFocusRight
538 * nextFocusUp
539 * </pre>
540 * </p>
541 *
542 *
543 * <p>
544 * To get a particular view to take focus, call {@link #requestFocus()}.
545 * </p>
546 *
547 * <a name="TouchMode"></a>
548 * <h3>Touch Mode</h3>
549 * <p>
550 * When a user is navigating a user interface via directional keys such as a D-pad, it is
551 * necessary to give focus to actionable items such as buttons so the user can see
552 * what will take input.  If the device has touch capabilities, however, and the user
553 * begins interacting with the interface by touching it, it is no longer necessary to
554 * always highlight, or give focus to, a particular view.  This motivates a mode
555 * for interaction named 'touch mode'.
556 * </p>
557 * <p>
558 * For a touch capable device, once the user touches the screen, the device
559 * will enter touch mode.  From this point onward, only views for which
560 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
561 * Other views that are touchable, like buttons, will not take focus when touched; they will
562 * only fire the on click listeners.
563 * </p>
564 * <p>
565 * Any time a user hits a directional key, such as a D-pad direction, the view device will
566 * exit touch mode, and find a view to take focus, so that the user may resume interacting
567 * with the user interface without touching the screen again.
568 * </p>
569 * <p>
570 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
571 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
572 * </p>
573 *
574 * <a name="Scrolling"></a>
575 * <h3>Scrolling</h3>
576 * <p>
577 * The framework provides basic support for views that wish to internally
578 * scroll their content. This includes keeping track of the X and Y scroll
579 * offset as well as mechanisms for drawing scrollbars. See
580 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
581 * {@link #awakenScrollBars()} for more details.
582 * </p>
583 *
584 * <a name="Tags"></a>
585 * <h3>Tags</h3>
586 * <p>
587 * Unlike IDs, tags are not used to identify views. Tags are essentially an
588 * extra piece of information that can be associated with a view. They are most
589 * often used as a convenience to store data related to views in the views
590 * themselves rather than by putting them in a separate structure.
591 * </p>
592 * <p>
593 * Tags may be specified with character sequence values in layout XML as either
594 * a single tag using the {@link android.R.styleable#View_tag android:tag}
595 * attribute or multiple tags using the {@code <tag>} child element:
596 * <pre>
597 *     &lt;View ...
598 *           android:tag="@string/mytag_value" /&gt;
599 *     &lt;View ...&gt;
600 *         &lt;tag android:id="@+id/mytag"
601 *              android:value="@string/mytag_value" /&gt;
602 *     &lt;/View>
603 * </pre>
604 * </p>
605 * <p>
606 * Tags may also be specified with arbitrary objects from code using
607 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
608 * </p>
609 *
610 * <a name="Themes"></a>
611 * <h3>Themes</h3>
612 * <p>
613 * By default, Views are created using the theme of the Context object supplied
614 * to their constructor; however, a different theme may be specified by using
615 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
616 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
617 * code.
618 * </p>
619 * <p>
620 * When the {@link android.R.styleable#View_theme android:theme} attribute is
621 * used in XML, the specified theme is applied on top of the inflation
622 * context's theme (see {@link LayoutInflater}) and used for the view itself as
623 * well as any child elements.
624 * </p>
625 * <p>
626 * In the following example, both views will be created using the Material dark
627 * color scheme; however, because an overlay theme is used which only defines a
628 * subset of attributes, the value of
629 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
630 * the inflation context's theme (e.g. the Activity theme) will be preserved.
631 * <pre>
632 *     &lt;LinearLayout
633 *             ...
634 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
635 *         &lt;View ...&gt;
636 *     &lt;/LinearLayout&gt;
637 * </pre>
638 * </p>
639 *
640 * <a name="Properties"></a>
641 * <h3>Properties</h3>
642 * <p>
643 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
644 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
645 * available both in the {@link Property} form as well as in similarly-named setter/getter
646 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
647 * be used to set persistent state associated with these rendering-related properties on the view.
648 * The properties and methods can also be used in conjunction with
649 * {@link android.animation.Animator Animator}-based animations, described more in the
650 * <a href="#Animation">Animation</a> section.
651 * </p>
652 *
653 * <a name="Animation"></a>
654 * <h3>Animation</h3>
655 * <p>
656 * Starting with Android 3.0, the preferred way of animating views is to use the
657 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
658 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
659 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
660 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
661 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
662 * makes animating these View properties particularly easy and efficient.
663 * </p>
664 * <p>
665 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
666 * You can attach an {@link Animation} object to a view using
667 * {@link #setAnimation(Animation)} or
668 * {@link #startAnimation(Animation)}. The animation can alter the scale,
669 * rotation, translation and alpha of a view over time. If the animation is
670 * attached to a view that has children, the animation will affect the entire
671 * subtree rooted by that node. When an animation is started, the framework will
672 * take care of redrawing the appropriate views until the animation completes.
673 * </p>
674 *
675 * <a name="Security"></a>
676 * <h3>Security</h3>
677 * <p>
678 * Sometimes it is essential that an application be able to verify that an action
679 * is being performed with the full knowledge and consent of the user, such as
680 * granting a permission request, making a purchase or clicking on an advertisement.
681 * Unfortunately, a malicious application could try to spoof the user into
682 * performing these actions, unaware, by concealing the intended purpose of the view.
683 * As a remedy, the framework offers a touch filtering mechanism that can be used to
684 * improve the security of views that provide access to sensitive functionality.
685 * </p><p>
686 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
687 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
688 * will discard touches that are received whenever the view's window is obscured by
689 * another visible window.  As a result, the view will not receive touches whenever a
690 * toast, dialog or other window appears above the view's window.
691 * </p><p>
692 * For more fine-grained control over security, consider overriding the
693 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
694 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
695 * </p>
696 *
697 * @attr ref android.R.styleable#View_alpha
698 * @attr ref android.R.styleable#View_background
699 * @attr ref android.R.styleable#View_clickable
700 * @attr ref android.R.styleable#View_contentDescription
701 * @attr ref android.R.styleable#View_drawingCacheQuality
702 * @attr ref android.R.styleable#View_duplicateParentState
703 * @attr ref android.R.styleable#View_id
704 * @attr ref android.R.styleable#View_requiresFadingEdge
705 * @attr ref android.R.styleable#View_fadeScrollbars
706 * @attr ref android.R.styleable#View_fadingEdgeLength
707 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
708 * @attr ref android.R.styleable#View_fitsSystemWindows
709 * @attr ref android.R.styleable#View_isScrollContainer
710 * @attr ref android.R.styleable#View_focusable
711 * @attr ref android.R.styleable#View_focusableInTouchMode
712 * @attr ref android.R.styleable#View_focusedByDefault
713 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
714 * @attr ref android.R.styleable#View_keepScreenOn
715 * @attr ref android.R.styleable#View_keyboardNavigationCluster
716 * @attr ref android.R.styleable#View_layerType
717 * @attr ref android.R.styleable#View_layoutDirection
718 * @attr ref android.R.styleable#View_longClickable
719 * @attr ref android.R.styleable#View_minHeight
720 * @attr ref android.R.styleable#View_minWidth
721 * @attr ref android.R.styleable#View_nextClusterForward
722 * @attr ref android.R.styleable#View_nextFocusDown
723 * @attr ref android.R.styleable#View_nextFocusLeft
724 * @attr ref android.R.styleable#View_nextFocusRight
725 * @attr ref android.R.styleable#View_nextFocusUp
726 * @attr ref android.R.styleable#View_onClick
727 * @attr ref android.R.styleable#View_padding
728 * @attr ref android.R.styleable#View_paddingHorizontal
729 * @attr ref android.R.styleable#View_paddingVertical
730 * @attr ref android.R.styleable#View_paddingBottom
731 * @attr ref android.R.styleable#View_paddingLeft
732 * @attr ref android.R.styleable#View_paddingRight
733 * @attr ref android.R.styleable#View_paddingTop
734 * @attr ref android.R.styleable#View_paddingStart
735 * @attr ref android.R.styleable#View_paddingEnd
736 * @attr ref android.R.styleable#View_saveEnabled
737 * @attr ref android.R.styleable#View_rotation
738 * @attr ref android.R.styleable#View_rotationX
739 * @attr ref android.R.styleable#View_rotationY
740 * @attr ref android.R.styleable#View_scaleX
741 * @attr ref android.R.styleable#View_scaleY
742 * @attr ref android.R.styleable#View_scrollX
743 * @attr ref android.R.styleable#View_scrollY
744 * @attr ref android.R.styleable#View_scrollbarSize
745 * @attr ref android.R.styleable#View_scrollbarStyle
746 * @attr ref android.R.styleable#View_scrollbars
747 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
748 * @attr ref android.R.styleable#View_scrollbarFadeDuration
749 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
750 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
751 * @attr ref android.R.styleable#View_scrollbarThumbVertical
752 * @attr ref android.R.styleable#View_scrollbarTrackVertical
753 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
754 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
755 * @attr ref android.R.styleable#View_stateListAnimator
756 * @attr ref android.R.styleable#View_transitionName
757 * @attr ref android.R.styleable#View_soundEffectsEnabled
758 * @attr ref android.R.styleable#View_tag
759 * @attr ref android.R.styleable#View_textAlignment
760 * @attr ref android.R.styleable#View_textDirection
761 * @attr ref android.R.styleable#View_transformPivotX
762 * @attr ref android.R.styleable#View_transformPivotY
763 * @attr ref android.R.styleable#View_translationX
764 * @attr ref android.R.styleable#View_translationY
765 * @attr ref android.R.styleable#View_translationZ
766 * @attr ref android.R.styleable#View_visibility
767 * @attr ref android.R.styleable#View_theme
768 *
769 * @see android.view.ViewGroup
770 */
771@UiThread
772public class View implements Drawable.Callback, KeyEvent.Callback,
773        AccessibilityEventSource {
774    private static final boolean DBG = false;
775
776    /** @hide */
777    public static boolean DEBUG_DRAW = false;
778
779    /**
780     * The logging tag used by this class with android.util.Log.
781     */
782    protected static final String VIEW_LOG_TAG = "View";
783
784    /**
785     * When set to true, apps will draw debugging information about their layouts.
786     *
787     * @hide
788     */
789    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
790
791    /**
792     * When set to true, this view will save its attribute data.
793     *
794     * @hide
795     */
796    public static boolean mDebugViewAttributes = false;
797
798    /**
799     * Used to mark a View that has no ID.
800     */
801    public static final int NO_ID = -1;
802
803    /**
804     * Last ID that is given to Views that are no part of activities.
805     *
806     * {@hide}
807     */
808    public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
809
810    /**
811     * Attribute to find the autofilled highlight
812     *
813     * @see #getAutofilledDrawable()
814     */
815    private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
816            new int[]{android.R.attr.autofilledHighlight};
817
818    /**
819     * Signals that compatibility booleans have been initialized according to
820     * target SDK versions.
821     */
822    private static boolean sCompatibilityDone = false;
823
824    /**
825     * Use the old (broken) way of building MeasureSpecs.
826     */
827    private static boolean sUseBrokenMakeMeasureSpec = false;
828
829    /**
830     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
831     */
832    static boolean sUseZeroUnspecifiedMeasureSpec = false;
833
834    /**
835     * Ignore any optimizations using the measure cache.
836     */
837    private static boolean sIgnoreMeasureCache = false;
838
839    /**
840     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
841     */
842    private static boolean sAlwaysRemeasureExactly = false;
843
844    /**
845     * Relax constraints around whether setLayoutParams() must be called after
846     * modifying the layout params.
847     */
848    private static boolean sLayoutParamsAlwaysChanged = false;
849
850    /**
851     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
852     * without throwing
853     */
854    static boolean sTextureViewIgnoresDrawableSetters = false;
855
856    /**
857     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
858     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
859     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
860     * check is implemented for backwards compatibility.
861     *
862     * {@hide}
863     */
864    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
865
866    /**
867     * Prior to N, when drag enters into child of a view that has already received an
868     * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
869     * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
870     * false from its event handler for these events.
871     * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
872     * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
873     * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
874     */
875    static boolean sCascadedDragDrop;
876
877    /**
878     * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
879     * to determine things like whether or not to permit item click events. We can't break
880     * apps that do this just because more things (clickable things) are now auto-focusable
881     * and they would get different results, so give old behavior to old apps.
882     */
883    static boolean sHasFocusableExcludeAutoFocusable;
884
885    /**
886     * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
887     * made focusable by default. As a result, apps could (incorrectly) change the clickable
888     * setting of views off the UI thread. Now that clickable can effect the focusable state,
889     * changing the clickable attribute off the UI thread will cause an exception (since changing
890     * the focusable state checks). In order to prevent apps from crashing, we will handle this
891     * specific case and just not notify parents on new focusables resulting from marking views
892     * clickable from outside the UI thread.
893     */
894    private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
895
896    /** @hide */
897    @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
898    @Retention(RetentionPolicy.SOURCE)
899    public @interface Focusable {}
900
901    /**
902     * This view does not want keystrokes.
903     * <p>
904     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
905     * android:focusable}.
906     */
907    public static final int NOT_FOCUSABLE = 0x00000000;
908
909    /**
910     * This view wants keystrokes.
911     * <p>
912     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
913     * android:focusable}.
914     */
915    public static final int FOCUSABLE = 0x00000001;
916
917    /**
918     * This view determines focusability automatically. This is the default.
919     * <p>
920     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
921     * android:focusable}.
922     */
923    public static final int FOCUSABLE_AUTO = 0x00000010;
924
925    /**
926     * Mask for use with setFlags indicating bits used for focus.
927     */
928    private static final int FOCUSABLE_MASK = 0x00000011;
929
930    /**
931     * This view will adjust its padding to fit sytem windows (e.g. status bar)
932     */
933    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
934
935    /** @hide */
936    @IntDef({VISIBLE, INVISIBLE, GONE})
937    @Retention(RetentionPolicy.SOURCE)
938    public @interface Visibility {}
939
940    /**
941     * This view is visible.
942     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
943     * android:visibility}.
944     */
945    public static final int VISIBLE = 0x00000000;
946
947    /**
948     * This view is invisible, but it still takes up space for layout purposes.
949     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
950     * android:visibility}.
951     */
952    public static final int INVISIBLE = 0x00000004;
953
954    /**
955     * This view is invisible, and it doesn't take any space for layout
956     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
957     * android:visibility}.
958     */
959    public static final int GONE = 0x00000008;
960
961    /**
962     * Mask for use with setFlags indicating bits used for visibility.
963     * {@hide}
964     */
965    static final int VISIBILITY_MASK = 0x0000000C;
966
967    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
968
969    /**
970     * Hint indicating that this view can be autofilled with an email address.
971     *
972     * <p>Can be used with either {@link #setAutofillHints(String[])} or
973     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
974     * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
975     *
976     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
977     */
978    public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
979
980    /**
981     * Hint indicating that this view can be autofilled with a user's real name.
982     *
983     * <p>Can be used with either {@link #setAutofillHints(String[])} or
984     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
985     * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
986     *
987     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
988     */
989    public static final String AUTOFILL_HINT_NAME = "name";
990
991    /**
992     * Hint indicating that this view can be autofilled with a username.
993     *
994     * <p>Can be used with either {@link #setAutofillHints(String[])} or
995     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
996     * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
997     *
998     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
999     */
1000    public static final String AUTOFILL_HINT_USERNAME = "username";
1001
1002    /**
1003     * Hint indicating that this view can be autofilled with a password.
1004     *
1005     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1006     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1007     * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1008     *
1009     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1010     */
1011    public static final String AUTOFILL_HINT_PASSWORD = "password";
1012
1013    /**
1014     * Hint indicating that this view can be autofilled with a phone number.
1015     *
1016     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1017     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1018     * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1019     *
1020     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1021     */
1022    public static final String AUTOFILL_HINT_PHONE = "phone";
1023
1024    /**
1025     * Hint indicating that this view can be autofilled with a postal address.
1026     *
1027     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1028     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1029     * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1030     *
1031     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1032     */
1033    public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1034
1035    /**
1036     * Hint indicating that this view can be autofilled with a postal code.
1037     *
1038     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1039     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1040     * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1041     *
1042     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1043     */
1044    public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1045
1046    /**
1047     * Hint indicating that this view can be autofilled with a credit card number.
1048     *
1049     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1050     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1051     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1052     *
1053     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1054     */
1055    public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1056
1057    /**
1058     * Hint indicating that this view can be autofilled with a credit card security code.
1059     *
1060     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1061     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1062     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1063     *
1064     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1065     */
1066    public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1067
1068    /**
1069     * Hint indicating that this view can be autofilled with a credit card expiration date.
1070     *
1071     * <p>It should be used when the credit card expiration date is represented by just one view;
1072     * if it is represented by more than one (for example, one view for the month and another view
1073     * for the year), then each of these views should use the hint specific for the unit
1074     * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1075     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1076     * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1077     *
1078     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1079     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1080     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1081     *
1082     * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
1083     * avoid ambiguity when the autofill service provides a value for it. To understand why a
1084     * value can be ambiguous, consider "April of 2020", which could be represented as either of
1085     * the following options:
1086     *
1087     * <ul>
1088     *   <li>{@code "04/2020"}
1089     *   <li>{@code "4/2020"}
1090     *   <li>{@code "2020/04"}
1091     *   <li>{@code "2020/4"}
1092     *   <li>{@code "April/2020"}
1093     *   <li>{@code "Apr/2020"}
1094     * </ul>
1095     *
1096     * <p>You define a date autofill value for the view by overriding the following methods:
1097     *
1098     * <ol>
1099     *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
1100     *   <li>{@link #getAutofillValue()} to return a
1101     *       {@link AutofillValue#forDate(long) date autofillvalue}.
1102     *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
1103     * </ol>
1104     *
1105     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1106     */
1107    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1108            "creditCardExpirationDate";
1109
1110    /**
1111     * Hint indicating that this view can be autofilled with a credit card expiration month.
1112     *
1113     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1114     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1115     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1116     *
1117     * <p>When annotating a view with this hint, it's recommended to use a text autofill value
1118     * whose value is the numerical representation of the month, starting on {@code 1} to avoid
1119     * ambiguity when the autofill service provides a value for it. To understand why a
1120     * value can be ambiguous, consider "January", which could be represented as either of
1121     *
1122     * <ul>
1123     *   <li>{@code "1"}: recommended way.
1124     *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
1125     *   <li>{@code "January"}: full name, in English.
1126     *   <li>{@code "jan"}: abbreviated name, in English.
1127     *   <li>{@code "Janeiro"}: full name, in another language.
1128     * </ul>
1129     *
1130     * <p>Another recommended approach is to use a date autofill value - see
1131     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
1132     *
1133     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1134     */
1135    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1136            "creditCardExpirationMonth";
1137
1138    /**
1139     * Hint indicating that this view can be autofilled with a credit card expiration year.
1140     *
1141     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1142     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1143     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1144     *
1145     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1146     */
1147    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1148            "creditCardExpirationYear";
1149
1150    /**
1151     * Hint indicating that this view can be autofilled with a credit card expiration day.
1152     *
1153     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1154     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1155     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
1156     *
1157     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1158     */
1159    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1160
1161    /**
1162     * Hints for the autofill services that describes the content of the view.
1163     */
1164    private @Nullable String[] mAutofillHints;
1165
1166    /**
1167     * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1168     */
1169    private AutofillId mAutofillId;
1170
1171    /** @hide */
1172    @IntDef({
1173            AUTOFILL_TYPE_NONE,
1174            AUTOFILL_TYPE_TEXT,
1175            AUTOFILL_TYPE_TOGGLE,
1176            AUTOFILL_TYPE_LIST,
1177            AUTOFILL_TYPE_DATE
1178    })
1179    @Retention(RetentionPolicy.SOURCE)
1180    public @interface AutofillType {}
1181
1182    /**
1183     * Autofill type for views that cannot be autofilled.
1184     *
1185     * <p>Typically used when the view is read-only; for example, a text label.
1186     *
1187     * @see #getAutofillType()
1188     */
1189    public static final int AUTOFILL_TYPE_NONE = 0;
1190
1191    /**
1192     * Autofill type for a text field, which is filled by a {@link CharSequence}.
1193     *
1194     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1195     * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1196     * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1197     *
1198     * @see #getAutofillType()
1199     */
1200    public static final int AUTOFILL_TYPE_TEXT = 1;
1201
1202    /**
1203     * Autofill type for a togglable field, which is filled by a {@code boolean}.
1204     *
1205     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1206     * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1207     * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1208     *
1209     * @see #getAutofillType()
1210     */
1211    public static final int AUTOFILL_TYPE_TOGGLE = 2;
1212
1213    /**
1214     * Autofill type for a selection list field, which is filled by an {@code int}
1215     * representing the element index inside the list (starting at {@code 0}).
1216     *
1217     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1218     * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1219     * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1220     *
1221     * <p>The available options in the selection list are typically provided by
1222     * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1223     *
1224     * @see #getAutofillType()
1225     */
1226    public static final int AUTOFILL_TYPE_LIST = 3;
1227
1228
1229    /**
1230     * Autofill type for a field that contains a date, which is represented by a long representing
1231     * the number of milliseconds since the standard base time known as "the epoch", namely
1232     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1233     *
1234     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1235     * {@link AutofillValue#forDate(long)}, and the values passed to
1236     * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1237     *
1238     * @see #getAutofillType()
1239     */
1240    public static final int AUTOFILL_TYPE_DATE = 4;
1241
1242    /** @hide */
1243    @IntDef({
1244            IMPORTANT_FOR_AUTOFILL_AUTO,
1245            IMPORTANT_FOR_AUTOFILL_YES,
1246            IMPORTANT_FOR_AUTOFILL_NO,
1247            IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1248            IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1249    })
1250    @Retention(RetentionPolicy.SOURCE)
1251    public @interface AutofillImportance {}
1252
1253    /**
1254     * Automatically determine whether a view is important for autofill.
1255     *
1256     * @see #isImportantForAutofill()
1257     * @see #setImportantForAutofill(int)
1258     */
1259    public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1260
1261    /**
1262     * The view is important for autofill, and its children (if any) will be traversed.
1263     *
1264     * @see #isImportantForAutofill()
1265     * @see #setImportantForAutofill(int)
1266     */
1267    public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1268
1269    /**
1270     * The view is not important for autofill, but its children (if any) will be traversed.
1271     *
1272     * @see #isImportantForAutofill()
1273     * @see #setImportantForAutofill(int)
1274     */
1275    public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1276
1277    /**
1278     * The view is important for autofill, but its children (if any) will not be traversed.
1279     *
1280     * @see #isImportantForAutofill()
1281     * @see #setImportantForAutofill(int)
1282     */
1283    public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1284
1285    /**
1286     * The view is not important for autofill, and its children (if any) will not be traversed.
1287     *
1288     * @see #isImportantForAutofill()
1289     * @see #setImportantForAutofill(int)
1290     */
1291    public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1292
1293    /** @hide */
1294    @IntDef(
1295            flag = true,
1296            value = {AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS})
1297    @Retention(RetentionPolicy.SOURCE)
1298    public @interface AutofillFlags {}
1299
1300    /**
1301     * Flag requesting you to add views that are marked as not important for autofill
1302     * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1303     */
1304    public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1305
1306    /**
1307     * This view is enabled. Interpretation varies by subclass.
1308     * Use with ENABLED_MASK when calling setFlags.
1309     * {@hide}
1310     */
1311    static final int ENABLED = 0x00000000;
1312
1313    /**
1314     * This view is disabled. Interpretation varies by subclass.
1315     * Use with ENABLED_MASK when calling setFlags.
1316     * {@hide}
1317     */
1318    static final int DISABLED = 0x00000020;
1319
1320   /**
1321    * Mask for use with setFlags indicating bits used for indicating whether
1322    * this view is enabled
1323    * {@hide}
1324    */
1325    static final int ENABLED_MASK = 0x00000020;
1326
1327    /**
1328     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1329     * called and further optimizations will be performed. It is okay to have
1330     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1331     * {@hide}
1332     */
1333    static final int WILL_NOT_DRAW = 0x00000080;
1334
1335    /**
1336     * Mask for use with setFlags indicating bits used for indicating whether
1337     * this view is will draw
1338     * {@hide}
1339     */
1340    static final int DRAW_MASK = 0x00000080;
1341
1342    /**
1343     * <p>This view doesn't show scrollbars.</p>
1344     * {@hide}
1345     */
1346    static final int SCROLLBARS_NONE = 0x00000000;
1347
1348    /**
1349     * <p>This view shows horizontal scrollbars.</p>
1350     * {@hide}
1351     */
1352    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1353
1354    /**
1355     * <p>This view shows vertical scrollbars.</p>
1356     * {@hide}
1357     */
1358    static final int SCROLLBARS_VERTICAL = 0x00000200;
1359
1360    /**
1361     * <p>Mask for use with setFlags indicating bits used for indicating which
1362     * scrollbars are enabled.</p>
1363     * {@hide}
1364     */
1365    static final int SCROLLBARS_MASK = 0x00000300;
1366
1367    /**
1368     * Indicates that the view should filter touches when its window is obscured.
1369     * Refer to the class comments for more information about this security feature.
1370     * {@hide}
1371     */
1372    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1373
1374    /**
1375     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1376     * that they are optional and should be skipped if the window has
1377     * requested system UI flags that ignore those insets for layout.
1378     */
1379    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1380
1381    /**
1382     * <p>This view doesn't show fading edges.</p>
1383     * {@hide}
1384     */
1385    static final int FADING_EDGE_NONE = 0x00000000;
1386
1387    /**
1388     * <p>This view shows horizontal fading edges.</p>
1389     * {@hide}
1390     */
1391    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1392
1393    /**
1394     * <p>This view shows vertical fading edges.</p>
1395     * {@hide}
1396     */
1397    static final int FADING_EDGE_VERTICAL = 0x00002000;
1398
1399    /**
1400     * <p>Mask for use with setFlags indicating bits used for indicating which
1401     * fading edges are enabled.</p>
1402     * {@hide}
1403     */
1404    static final int FADING_EDGE_MASK = 0x00003000;
1405
1406    /**
1407     * <p>Indicates this view can be clicked. When clickable, a View reacts
1408     * to clicks by notifying the OnClickListener.<p>
1409     * {@hide}
1410     */
1411    static final int CLICKABLE = 0x00004000;
1412
1413    /**
1414     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1415     * {@hide}
1416     */
1417    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1418
1419    /**
1420     * <p>Indicates that no icicle should be saved for this view.<p>
1421     * {@hide}
1422     */
1423    static final int SAVE_DISABLED = 0x000010000;
1424
1425    /**
1426     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1427     * property.</p>
1428     * {@hide}
1429     */
1430    static final int SAVE_DISABLED_MASK = 0x000010000;
1431
1432    /**
1433     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1434     * {@hide}
1435     */
1436    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1437
1438    /**
1439     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1440     * {@hide}
1441     */
1442    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1443
1444    /** @hide */
1445    @Retention(RetentionPolicy.SOURCE)
1446    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1447    public @interface DrawingCacheQuality {}
1448
1449    /**
1450     * <p>Enables low quality mode for the drawing cache.</p>
1451     */
1452    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1453
1454    /**
1455     * <p>Enables high quality mode for the drawing cache.</p>
1456     */
1457    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1458
1459    /**
1460     * <p>Enables automatic quality mode for the drawing cache.</p>
1461     */
1462    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1463
1464    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1465            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1466    };
1467
1468    /**
1469     * <p>Mask for use with setFlags indicating bits used for the cache
1470     * quality property.</p>
1471     * {@hide}
1472     */
1473    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1474
1475    /**
1476     * <p>
1477     * Indicates this view can be long clicked. When long clickable, a View
1478     * reacts to long clicks by notifying the OnLongClickListener or showing a
1479     * context menu.
1480     * </p>
1481     * {@hide}
1482     */
1483    static final int LONG_CLICKABLE = 0x00200000;
1484
1485    /**
1486     * <p>Indicates that this view gets its drawable states from its direct parent
1487     * and ignores its original internal states.</p>
1488     *
1489     * @hide
1490     */
1491    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1492
1493    /**
1494     * <p>
1495     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1496     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1497     * OnContextClickListener.
1498     * </p>
1499     * {@hide}
1500     */
1501    static final int CONTEXT_CLICKABLE = 0x00800000;
1502
1503
1504    /** @hide */
1505    @IntDef({
1506        SCROLLBARS_INSIDE_OVERLAY,
1507        SCROLLBARS_INSIDE_INSET,
1508        SCROLLBARS_OUTSIDE_OVERLAY,
1509        SCROLLBARS_OUTSIDE_INSET
1510    })
1511    @Retention(RetentionPolicy.SOURCE)
1512    public @interface ScrollBarStyle {}
1513
1514    /**
1515     * The scrollbar style to display the scrollbars inside the content area,
1516     * without increasing the padding. The scrollbars will be overlaid with
1517     * translucency on the view's content.
1518     */
1519    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1520
1521    /**
1522     * The scrollbar style to display the scrollbars inside the padded area,
1523     * increasing the padding of the view. The scrollbars will not overlap the
1524     * content area of the view.
1525     */
1526    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1527
1528    /**
1529     * The scrollbar style to display the scrollbars at the edge of the view,
1530     * without increasing the padding. The scrollbars will be overlaid with
1531     * translucency.
1532     */
1533    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1534
1535    /**
1536     * The scrollbar style to display the scrollbars at the edge of the view,
1537     * increasing the padding of the view. The scrollbars will only overlap the
1538     * background, if any.
1539     */
1540    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1541
1542    /**
1543     * Mask to check if the scrollbar style is overlay or inset.
1544     * {@hide}
1545     */
1546    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1547
1548    /**
1549     * Mask to check if the scrollbar style is inside or outside.
1550     * {@hide}
1551     */
1552    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1553
1554    /**
1555     * Mask for scrollbar style.
1556     * {@hide}
1557     */
1558    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1559
1560    /**
1561     * View flag indicating that the screen should remain on while the
1562     * window containing this view is visible to the user.  This effectively
1563     * takes care of automatically setting the WindowManager's
1564     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1565     */
1566    public static final int KEEP_SCREEN_ON = 0x04000000;
1567
1568    /**
1569     * View flag indicating whether this view should have sound effects enabled
1570     * for events such as clicking and touching.
1571     */
1572    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1573
1574    /**
1575     * View flag indicating whether this view should have haptic feedback
1576     * enabled for events such as long presses.
1577     */
1578    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1579
1580    /**
1581     * <p>Indicates that the view hierarchy should stop saving state when
1582     * it reaches this view.  If state saving is initiated immediately at
1583     * the view, it will be allowed.
1584     * {@hide}
1585     */
1586    static final int PARENT_SAVE_DISABLED = 0x20000000;
1587
1588    /**
1589     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1590     * {@hide}
1591     */
1592    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1593
1594    private static Paint sDebugPaint;
1595
1596    /**
1597     * <p>Indicates this view can display a tooltip on hover or long press.</p>
1598     * {@hide}
1599     */
1600    static final int TOOLTIP = 0x40000000;
1601
1602    /** @hide */
1603    @IntDef(flag = true,
1604            value = {
1605                FOCUSABLES_ALL,
1606                FOCUSABLES_TOUCH_MODE
1607            })
1608    @Retention(RetentionPolicy.SOURCE)
1609    public @interface FocusableMode {}
1610
1611    /**
1612     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1613     * should add all focusable Views regardless if they are focusable in touch mode.
1614     */
1615    public static final int FOCUSABLES_ALL = 0x00000000;
1616
1617    /**
1618     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1619     * should add only Views focusable in touch mode.
1620     */
1621    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1622
1623    /** @hide */
1624    @IntDef({
1625            FOCUS_BACKWARD,
1626            FOCUS_FORWARD,
1627            FOCUS_LEFT,
1628            FOCUS_UP,
1629            FOCUS_RIGHT,
1630            FOCUS_DOWN
1631    })
1632    @Retention(RetentionPolicy.SOURCE)
1633    public @interface FocusDirection {}
1634
1635    /** @hide */
1636    @IntDef({
1637            FOCUS_LEFT,
1638            FOCUS_UP,
1639            FOCUS_RIGHT,
1640            FOCUS_DOWN
1641    })
1642    @Retention(RetentionPolicy.SOURCE)
1643    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1644
1645    /**
1646     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1647     * item.
1648     */
1649    public static final int FOCUS_BACKWARD = 0x00000001;
1650
1651    /**
1652     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1653     * item.
1654     */
1655    public static final int FOCUS_FORWARD = 0x00000002;
1656
1657    /**
1658     * Use with {@link #focusSearch(int)}. Move focus to the left.
1659     */
1660    public static final int FOCUS_LEFT = 0x00000011;
1661
1662    /**
1663     * Use with {@link #focusSearch(int)}. Move focus up.
1664     */
1665    public static final int FOCUS_UP = 0x00000021;
1666
1667    /**
1668     * Use with {@link #focusSearch(int)}. Move focus to the right.
1669     */
1670    public static final int FOCUS_RIGHT = 0x00000042;
1671
1672    /**
1673     * Use with {@link #focusSearch(int)}. Move focus down.
1674     */
1675    public static final int FOCUS_DOWN = 0x00000082;
1676
1677    /**
1678     * Bits of {@link #getMeasuredWidthAndState()} and
1679     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1680     */
1681    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1682
1683    /**
1684     * Bits of {@link #getMeasuredWidthAndState()} and
1685     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1686     */
1687    public static final int MEASURED_STATE_MASK = 0xff000000;
1688
1689    /**
1690     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1691     * for functions that combine both width and height into a single int,
1692     * such as {@link #getMeasuredState()} and the childState argument of
1693     * {@link #resolveSizeAndState(int, int, int)}.
1694     */
1695    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1696
1697    /**
1698     * Bit of {@link #getMeasuredWidthAndState()} and
1699     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1700     * is smaller that the space the view would like to have.
1701     */
1702    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1703
1704    /**
1705     * Base View state sets
1706     */
1707    // Singles
1708    /**
1709     * Indicates the view has no states set. States are used with
1710     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1711     * view depending on its state.
1712     *
1713     * @see android.graphics.drawable.Drawable
1714     * @see #getDrawableState()
1715     */
1716    protected static final int[] EMPTY_STATE_SET;
1717    /**
1718     * Indicates the view is enabled. States are used with
1719     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1720     * view depending on its state.
1721     *
1722     * @see android.graphics.drawable.Drawable
1723     * @see #getDrawableState()
1724     */
1725    protected static final int[] ENABLED_STATE_SET;
1726    /**
1727     * Indicates the view is focused. States are used with
1728     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1729     * view depending on its state.
1730     *
1731     * @see android.graphics.drawable.Drawable
1732     * @see #getDrawableState()
1733     */
1734    protected static final int[] FOCUSED_STATE_SET;
1735    /**
1736     * Indicates the view is selected. States are used with
1737     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1738     * view depending on its state.
1739     *
1740     * @see android.graphics.drawable.Drawable
1741     * @see #getDrawableState()
1742     */
1743    protected static final int[] SELECTED_STATE_SET;
1744    /**
1745     * Indicates the view is pressed. States are used with
1746     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1747     * view depending on its state.
1748     *
1749     * @see android.graphics.drawable.Drawable
1750     * @see #getDrawableState()
1751     */
1752    protected static final int[] PRESSED_STATE_SET;
1753    /**
1754     * Indicates the view's window has focus. States are used with
1755     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1756     * view depending on its state.
1757     *
1758     * @see android.graphics.drawable.Drawable
1759     * @see #getDrawableState()
1760     */
1761    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1762    // Doubles
1763    /**
1764     * Indicates the view is enabled and has the focus.
1765     *
1766     * @see #ENABLED_STATE_SET
1767     * @see #FOCUSED_STATE_SET
1768     */
1769    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1770    /**
1771     * Indicates the view is enabled and selected.
1772     *
1773     * @see #ENABLED_STATE_SET
1774     * @see #SELECTED_STATE_SET
1775     */
1776    protected static final int[] ENABLED_SELECTED_STATE_SET;
1777    /**
1778     * Indicates the view is enabled and that its window has focus.
1779     *
1780     * @see #ENABLED_STATE_SET
1781     * @see #WINDOW_FOCUSED_STATE_SET
1782     */
1783    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1784    /**
1785     * Indicates the view is focused and selected.
1786     *
1787     * @see #FOCUSED_STATE_SET
1788     * @see #SELECTED_STATE_SET
1789     */
1790    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1791    /**
1792     * Indicates the view has the focus and that its window has the focus.
1793     *
1794     * @see #FOCUSED_STATE_SET
1795     * @see #WINDOW_FOCUSED_STATE_SET
1796     */
1797    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1798    /**
1799     * Indicates the view is selected and that its window has the focus.
1800     *
1801     * @see #SELECTED_STATE_SET
1802     * @see #WINDOW_FOCUSED_STATE_SET
1803     */
1804    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1805    // Triples
1806    /**
1807     * Indicates the view is enabled, focused and selected.
1808     *
1809     * @see #ENABLED_STATE_SET
1810     * @see #FOCUSED_STATE_SET
1811     * @see #SELECTED_STATE_SET
1812     */
1813    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1814    /**
1815     * Indicates the view is enabled, focused and its window has the focus.
1816     *
1817     * @see #ENABLED_STATE_SET
1818     * @see #FOCUSED_STATE_SET
1819     * @see #WINDOW_FOCUSED_STATE_SET
1820     */
1821    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1822    /**
1823     * Indicates the view is enabled, selected and its window has the focus.
1824     *
1825     * @see #ENABLED_STATE_SET
1826     * @see #SELECTED_STATE_SET
1827     * @see #WINDOW_FOCUSED_STATE_SET
1828     */
1829    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1830    /**
1831     * Indicates the view is focused, selected and its window has the focus.
1832     *
1833     * @see #FOCUSED_STATE_SET
1834     * @see #SELECTED_STATE_SET
1835     * @see #WINDOW_FOCUSED_STATE_SET
1836     */
1837    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1838    /**
1839     * Indicates the view is enabled, focused, selected and its window
1840     * has the focus.
1841     *
1842     * @see #ENABLED_STATE_SET
1843     * @see #FOCUSED_STATE_SET
1844     * @see #SELECTED_STATE_SET
1845     * @see #WINDOW_FOCUSED_STATE_SET
1846     */
1847    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1848    /**
1849     * Indicates the view is pressed and its window has the focus.
1850     *
1851     * @see #PRESSED_STATE_SET
1852     * @see #WINDOW_FOCUSED_STATE_SET
1853     */
1854    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1855    /**
1856     * Indicates the view is pressed and selected.
1857     *
1858     * @see #PRESSED_STATE_SET
1859     * @see #SELECTED_STATE_SET
1860     */
1861    protected static final int[] PRESSED_SELECTED_STATE_SET;
1862    /**
1863     * Indicates the view is pressed, selected and its window has the focus.
1864     *
1865     * @see #PRESSED_STATE_SET
1866     * @see #SELECTED_STATE_SET
1867     * @see #WINDOW_FOCUSED_STATE_SET
1868     */
1869    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1870    /**
1871     * Indicates the view is pressed and focused.
1872     *
1873     * @see #PRESSED_STATE_SET
1874     * @see #FOCUSED_STATE_SET
1875     */
1876    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1877    /**
1878     * Indicates the view is pressed, focused and its window has the focus.
1879     *
1880     * @see #PRESSED_STATE_SET
1881     * @see #FOCUSED_STATE_SET
1882     * @see #WINDOW_FOCUSED_STATE_SET
1883     */
1884    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1885    /**
1886     * Indicates the view is pressed, focused and selected.
1887     *
1888     * @see #PRESSED_STATE_SET
1889     * @see #SELECTED_STATE_SET
1890     * @see #FOCUSED_STATE_SET
1891     */
1892    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1893    /**
1894     * Indicates the view is pressed, focused, selected and its window has the focus.
1895     *
1896     * @see #PRESSED_STATE_SET
1897     * @see #FOCUSED_STATE_SET
1898     * @see #SELECTED_STATE_SET
1899     * @see #WINDOW_FOCUSED_STATE_SET
1900     */
1901    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1902    /**
1903     * Indicates the view is pressed and enabled.
1904     *
1905     * @see #PRESSED_STATE_SET
1906     * @see #ENABLED_STATE_SET
1907     */
1908    protected static final int[] PRESSED_ENABLED_STATE_SET;
1909    /**
1910     * Indicates the view is pressed, enabled and its window has the focus.
1911     *
1912     * @see #PRESSED_STATE_SET
1913     * @see #ENABLED_STATE_SET
1914     * @see #WINDOW_FOCUSED_STATE_SET
1915     */
1916    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1917    /**
1918     * Indicates the view is pressed, enabled and selected.
1919     *
1920     * @see #PRESSED_STATE_SET
1921     * @see #ENABLED_STATE_SET
1922     * @see #SELECTED_STATE_SET
1923     */
1924    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1925    /**
1926     * Indicates the view is pressed, enabled, selected and its window has the
1927     * focus.
1928     *
1929     * @see #PRESSED_STATE_SET
1930     * @see #ENABLED_STATE_SET
1931     * @see #SELECTED_STATE_SET
1932     * @see #WINDOW_FOCUSED_STATE_SET
1933     */
1934    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1935    /**
1936     * Indicates the view is pressed, enabled and focused.
1937     *
1938     * @see #PRESSED_STATE_SET
1939     * @see #ENABLED_STATE_SET
1940     * @see #FOCUSED_STATE_SET
1941     */
1942    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1943    /**
1944     * Indicates the view is pressed, enabled, focused and its window has the
1945     * focus.
1946     *
1947     * @see #PRESSED_STATE_SET
1948     * @see #ENABLED_STATE_SET
1949     * @see #FOCUSED_STATE_SET
1950     * @see #WINDOW_FOCUSED_STATE_SET
1951     */
1952    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1953    /**
1954     * Indicates the view is pressed, enabled, focused and selected.
1955     *
1956     * @see #PRESSED_STATE_SET
1957     * @see #ENABLED_STATE_SET
1958     * @see #SELECTED_STATE_SET
1959     * @see #FOCUSED_STATE_SET
1960     */
1961    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1962    /**
1963     * Indicates the view is pressed, enabled, focused, selected and its window
1964     * has the focus.
1965     *
1966     * @see #PRESSED_STATE_SET
1967     * @see #ENABLED_STATE_SET
1968     * @see #SELECTED_STATE_SET
1969     * @see #FOCUSED_STATE_SET
1970     * @see #WINDOW_FOCUSED_STATE_SET
1971     */
1972    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1973
1974    static {
1975        EMPTY_STATE_SET = StateSet.get(0);
1976
1977        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1978
1979        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1980        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1981                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1982
1983        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1984        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1985                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1986        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1987                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1988        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1989                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1990                        | StateSet.VIEW_STATE_FOCUSED);
1991
1992        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1993        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1994                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1995        ENABLED_SELECTED_STATE_SET = StateSet.get(
1996                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1997        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1998                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1999                        | StateSet.VIEW_STATE_ENABLED);
2000        ENABLED_FOCUSED_STATE_SET = StateSet.get(
2001                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
2002        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2003                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2004                        | StateSet.VIEW_STATE_ENABLED);
2005        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2006                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2007                        | StateSet.VIEW_STATE_ENABLED);
2008        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2009                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2010                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
2011
2012        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
2013        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2014                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2015        PRESSED_SELECTED_STATE_SET = StateSet.get(
2016                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
2017        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2018                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2019                        | StateSet.VIEW_STATE_PRESSED);
2020        PRESSED_FOCUSED_STATE_SET = StateSet.get(
2021                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2022        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2023                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2024                        | StateSet.VIEW_STATE_PRESSED);
2025        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2026                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2027                        | StateSet.VIEW_STATE_PRESSED);
2028        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2029                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2030                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
2031        PRESSED_ENABLED_STATE_SET = StateSet.get(
2032                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2033        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2034                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
2035                        | StateSet.VIEW_STATE_PRESSED);
2036        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
2037                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
2038                        | StateSet.VIEW_STATE_PRESSED);
2039        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2040                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2041                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2042        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2043                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2044                        | StateSet.VIEW_STATE_PRESSED);
2045        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2046                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2047                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2048        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2049                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2050                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2051        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2052                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2053                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2054                        | StateSet.VIEW_STATE_PRESSED);
2055    }
2056
2057    /**
2058     * Accessibility event types that are dispatched for text population.
2059     */
2060    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2061            AccessibilityEvent.TYPE_VIEW_CLICKED
2062            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2063            | AccessibilityEvent.TYPE_VIEW_SELECTED
2064            | AccessibilityEvent.TYPE_VIEW_FOCUSED
2065            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2066            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2067            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2068            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2069            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2070            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2071            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2072
2073    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2074
2075    static final int DEBUG_CORNERS_SIZE_DIP = 8;
2076
2077    /**
2078     * Temporary Rect currently for use in setBackground().  This will probably
2079     * be extended in the future to hold our own class with more than just
2080     * a Rect. :)
2081     */
2082    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
2083
2084    /**
2085     * Map used to store views' tags.
2086     */
2087    private SparseArray<Object> mKeyedTags;
2088
2089    /**
2090     * The next available accessibility id.
2091     */
2092    private static int sNextAccessibilityViewId;
2093
2094    /**
2095     * The animation currently associated with this view.
2096     * @hide
2097     */
2098    protected Animation mCurrentAnimation = null;
2099
2100    /**
2101     * Width as measured during measure pass.
2102     * {@hide}
2103     */
2104    @ViewDebug.ExportedProperty(category = "measurement")
2105    int mMeasuredWidth;
2106
2107    /**
2108     * Height as measured during measure pass.
2109     * {@hide}
2110     */
2111    @ViewDebug.ExportedProperty(category = "measurement")
2112    int mMeasuredHeight;
2113
2114    /**
2115     * Flag to indicate that this view was marked INVALIDATED, or had its display list
2116     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2117     * its display list. This flag, used only when hw accelerated, allows us to clear the
2118     * flag while retaining this information until it's needed (at getDisplayList() time and
2119     * in drawChild(), when we decide to draw a view's children's display lists into our own).
2120     *
2121     * {@hide}
2122     */
2123    boolean mRecreateDisplayList = false;
2124
2125    /**
2126     * The view's identifier.
2127     * {@hide}
2128     *
2129     * @see #setId(int)
2130     * @see #getId()
2131     */
2132    @IdRes
2133    @ViewDebug.ExportedProperty(resolveId = true)
2134    int mID = NO_ID;
2135
2136    /** The ID of this view for autofill purposes.
2137     * <ul>
2138     *     <li>== {@link #NO_ID}: ID has not been assigned yet
2139     *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2140     *                                                  unique in the process. This might change
2141     *                                                  over activity lifecycle events.
2142     *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2143     *                                                  unique in the activity. This stays the same
2144     *                                                  over activity lifecycle events.
2145     */
2146    private int mAutofillViewId = NO_ID;
2147
2148    // ID for accessibility purposes. This ID must be unique for every window
2149    private int mAccessibilityViewId = NO_ID;
2150
2151    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2152
2153    /**
2154     * The view's tag.
2155     * {@hide}
2156     *
2157     * @see #setTag(Object)
2158     * @see #getTag()
2159     */
2160    protected Object mTag = null;
2161
2162    // for mPrivateFlags:
2163    /** {@hide} */
2164    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2165    /** {@hide} */
2166    static final int PFLAG_FOCUSED                     = 0x00000002;
2167    /** {@hide} */
2168    static final int PFLAG_SELECTED                    = 0x00000004;
2169    /** {@hide} */
2170    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2171    /** {@hide} */
2172    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2173    /** {@hide} */
2174    static final int PFLAG_DRAWN                       = 0x00000020;
2175    /**
2176     * When this flag is set, this view is running an animation on behalf of its
2177     * children and should therefore not cancel invalidate requests, even if they
2178     * lie outside of this view's bounds.
2179     *
2180     * {@hide}
2181     */
2182    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2183    /** {@hide} */
2184    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2185    /** {@hide} */
2186    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2187    /** {@hide} */
2188    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2189    /** {@hide} */
2190    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2191    /** {@hide} */
2192    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2193    /** {@hide} */
2194    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2195
2196    private static final int PFLAG_PRESSED             = 0x00004000;
2197
2198    /** {@hide} */
2199    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2200    /**
2201     * Flag used to indicate that this view should be drawn once more (and only once
2202     * more) after its animation has completed.
2203     * {@hide}
2204     */
2205    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2206
2207    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2208
2209    /**
2210     * Indicates that the View returned true when onSetAlpha() was called and that
2211     * the alpha must be restored.
2212     * {@hide}
2213     */
2214    static final int PFLAG_ALPHA_SET                   = 0x00040000;
2215
2216    /**
2217     * Set by {@link #setScrollContainer(boolean)}.
2218     */
2219    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2220
2221    /**
2222     * Set by {@link #setScrollContainer(boolean)}.
2223     */
2224    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2225
2226    /**
2227     * View flag indicating whether this view was invalidated (fully or partially.)
2228     *
2229     * @hide
2230     */
2231    static final int PFLAG_DIRTY                       = 0x00200000;
2232
2233    /**
2234     * View flag indicating whether this view was invalidated by an opaque
2235     * invalidate request.
2236     *
2237     * @hide
2238     */
2239    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2240
2241    /**
2242     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2243     *
2244     * @hide
2245     */
2246    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2247
2248    /**
2249     * Indicates whether the background is opaque.
2250     *
2251     * @hide
2252     */
2253    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2254
2255    /**
2256     * Indicates whether the scrollbars are opaque.
2257     *
2258     * @hide
2259     */
2260    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2261
2262    /**
2263     * Indicates whether the view is opaque.
2264     *
2265     * @hide
2266     */
2267    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2268
2269    /**
2270     * Indicates a prepressed state;
2271     * the short time between ACTION_DOWN and recognizing
2272     * a 'real' press. Prepressed is used to recognize quick taps
2273     * even when they are shorter than ViewConfiguration.getTapTimeout().
2274     *
2275     * @hide
2276     */
2277    private static final int PFLAG_PREPRESSED          = 0x02000000;
2278
2279    /**
2280     * Indicates whether the view is temporarily detached.
2281     *
2282     * @hide
2283     */
2284    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2285
2286    /**
2287     * Indicates that we should awaken scroll bars once attached
2288     *
2289     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2290     * during window attachment and it is no longer needed. Feel free to repurpose it.
2291     *
2292     * @hide
2293     */
2294    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2295
2296    /**
2297     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2298     * @hide
2299     */
2300    private static final int PFLAG_HOVERED             = 0x10000000;
2301
2302    /**
2303     * no longer needed, should be reused
2304     */
2305    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
2306
2307    /** {@hide} */
2308    static final int PFLAG_ACTIVATED                   = 0x40000000;
2309
2310    /**
2311     * Indicates that this view was specifically invalidated, not just dirtied because some
2312     * child view was invalidated. The flag is used to determine when we need to recreate
2313     * a view's display list (as opposed to just returning a reference to its existing
2314     * display list).
2315     *
2316     * @hide
2317     */
2318    static final int PFLAG_INVALIDATED                 = 0x80000000;
2319
2320    /**
2321     * Masks for mPrivateFlags2, as generated by dumpFlags():
2322     *
2323     * |-------|-------|-------|-------|
2324     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2325     *                                1  PFLAG2_DRAG_HOVERED
2326     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2327     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2328     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2329     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2330     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2331     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2332     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2333     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2334     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2335     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2336     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2337     *                         111       PFLAG2_TEXT_DIRECTION_MASK
2338     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2339     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2340     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2341     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2342     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2343     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2344     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2345     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2346     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2347     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2348     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2349     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2350     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2351     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2352     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2353     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2354     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2355     *     1                             PFLAG2_VIEW_QUICK_REJECTED
2356     *    1                              PFLAG2_PADDING_RESOLVED
2357     *   1                               PFLAG2_DRAWABLE_RESOLVED
2358     *  1                                PFLAG2_HAS_TRANSIENT_STATE
2359     * |-------|-------|-------|-------|
2360     */
2361
2362    /**
2363     * Indicates that this view has reported that it can accept the current drag's content.
2364     * Cleared when the drag operation concludes.
2365     * @hide
2366     */
2367    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2368
2369    /**
2370     * Indicates that this view is currently directly under the drag location in a
2371     * drag-and-drop operation involving content that it can accept.  Cleared when
2372     * the drag exits the view, or when the drag operation concludes.
2373     * @hide
2374     */
2375    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2376
2377    /** @hide */
2378    @IntDef({
2379        LAYOUT_DIRECTION_LTR,
2380        LAYOUT_DIRECTION_RTL,
2381        LAYOUT_DIRECTION_INHERIT,
2382        LAYOUT_DIRECTION_LOCALE
2383    })
2384    @Retention(RetentionPolicy.SOURCE)
2385    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2386    public @interface LayoutDir {}
2387
2388    /** @hide */
2389    @IntDef({
2390        LAYOUT_DIRECTION_LTR,
2391        LAYOUT_DIRECTION_RTL
2392    })
2393    @Retention(RetentionPolicy.SOURCE)
2394    public @interface ResolvedLayoutDir {}
2395
2396    /**
2397     * A flag to indicate that the layout direction of this view has not been defined yet.
2398     * @hide
2399     */
2400    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2401
2402    /**
2403     * Horizontal layout direction of this view is from Left to Right.
2404     * Use with {@link #setLayoutDirection}.
2405     */
2406    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2407
2408    /**
2409     * Horizontal layout direction of this view is from Right to Left.
2410     * Use with {@link #setLayoutDirection}.
2411     */
2412    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2413
2414    /**
2415     * Horizontal layout direction of this view is inherited from its parent.
2416     * Use with {@link #setLayoutDirection}.
2417     */
2418    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2419
2420    /**
2421     * Horizontal layout direction of this view is from deduced from the default language
2422     * script for the locale. Use with {@link #setLayoutDirection}.
2423     */
2424    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2425
2426    /**
2427     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2428     * @hide
2429     */
2430    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2431
2432    /**
2433     * Mask for use with private flags indicating bits used for horizontal layout direction.
2434     * @hide
2435     */
2436    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2437
2438    /**
2439     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2440     * right-to-left direction.
2441     * @hide
2442     */
2443    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2444
2445    /**
2446     * Indicates whether the view horizontal layout direction has been resolved.
2447     * @hide
2448     */
2449    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2450
2451    /**
2452     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2453     * @hide
2454     */
2455    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2456            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2457
2458    /*
2459     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2460     * flag value.
2461     * @hide
2462     */
2463    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2464            LAYOUT_DIRECTION_LTR,
2465            LAYOUT_DIRECTION_RTL,
2466            LAYOUT_DIRECTION_INHERIT,
2467            LAYOUT_DIRECTION_LOCALE
2468    };
2469
2470    /**
2471     * Default horizontal layout direction.
2472     */
2473    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2474
2475    /**
2476     * Default horizontal layout direction.
2477     * @hide
2478     */
2479    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2480
2481    /**
2482     * Text direction is inherited through {@link ViewGroup}
2483     */
2484    public static final int TEXT_DIRECTION_INHERIT = 0;
2485
2486    /**
2487     * Text direction is using "first strong algorithm". The first strong directional character
2488     * determines the paragraph direction. If there is no strong directional character, the
2489     * paragraph direction is the view's resolved layout direction.
2490     */
2491    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2492
2493    /**
2494     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2495     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2496     * If there are neither, the paragraph direction is the view's resolved layout direction.
2497     */
2498    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2499
2500    /**
2501     * Text direction is forced to LTR.
2502     */
2503    public static final int TEXT_DIRECTION_LTR = 3;
2504
2505    /**
2506     * Text direction is forced to RTL.
2507     */
2508    public static final int TEXT_DIRECTION_RTL = 4;
2509
2510    /**
2511     * Text direction is coming from the system Locale.
2512     */
2513    public static final int TEXT_DIRECTION_LOCALE = 5;
2514
2515    /**
2516     * Text direction is using "first strong algorithm". The first strong directional character
2517     * determines the paragraph direction. If there is no strong directional character, the
2518     * paragraph direction is LTR.
2519     */
2520    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2521
2522    /**
2523     * Text direction is using "first strong algorithm". The first strong directional character
2524     * determines the paragraph direction. If there is no strong directional character, the
2525     * paragraph direction is RTL.
2526     */
2527    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2528
2529    /**
2530     * Default text direction is inherited
2531     */
2532    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2533
2534    /**
2535     * Default resolved text direction
2536     * @hide
2537     */
2538    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2539
2540    /**
2541     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2542     * @hide
2543     */
2544    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2545
2546    /**
2547     * Mask for use with private flags indicating bits used for text direction.
2548     * @hide
2549     */
2550    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2551            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2552
2553    /**
2554     * Array of text direction flags for mapping attribute "textDirection" to correct
2555     * flag value.
2556     * @hide
2557     */
2558    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2559            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2560            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2561            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2562            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2563            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2564            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2565            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2566            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2567    };
2568
2569    /**
2570     * Indicates whether the view text direction has been resolved.
2571     * @hide
2572     */
2573    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2574            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2575
2576    /**
2577     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2578     * @hide
2579     */
2580    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2581
2582    /**
2583     * Mask for use with private flags indicating bits used for resolved text direction.
2584     * @hide
2585     */
2586    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2587            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2588
2589    /**
2590     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2591     * @hide
2592     */
2593    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2594            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2595
2596    /** @hide */
2597    @IntDef({
2598        TEXT_ALIGNMENT_INHERIT,
2599        TEXT_ALIGNMENT_GRAVITY,
2600        TEXT_ALIGNMENT_CENTER,
2601        TEXT_ALIGNMENT_TEXT_START,
2602        TEXT_ALIGNMENT_TEXT_END,
2603        TEXT_ALIGNMENT_VIEW_START,
2604        TEXT_ALIGNMENT_VIEW_END
2605    })
2606    @Retention(RetentionPolicy.SOURCE)
2607    public @interface TextAlignment {}
2608
2609    /**
2610     * Default text alignment. The text alignment of this View is inherited from its parent.
2611     * Use with {@link #setTextAlignment(int)}
2612     */
2613    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2614
2615    /**
2616     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2617     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2618     *
2619     * Use with {@link #setTextAlignment(int)}
2620     */
2621    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2622
2623    /**
2624     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2625     *
2626     * Use with {@link #setTextAlignment(int)}
2627     */
2628    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2629
2630    /**
2631     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2632     *
2633     * Use with {@link #setTextAlignment(int)}
2634     */
2635    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2636
2637    /**
2638     * Center the paragraph, e.g. ALIGN_CENTER.
2639     *
2640     * Use with {@link #setTextAlignment(int)}
2641     */
2642    public static final int TEXT_ALIGNMENT_CENTER = 4;
2643
2644    /**
2645     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2646     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2647     *
2648     * Use with {@link #setTextAlignment(int)}
2649     */
2650    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2651
2652    /**
2653     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2654     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2655     *
2656     * Use with {@link #setTextAlignment(int)}
2657     */
2658    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2659
2660    /**
2661     * Default text alignment is inherited
2662     */
2663    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2664
2665    /**
2666     * Default resolved text alignment
2667     * @hide
2668     */
2669    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2670
2671    /**
2672      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2673      * @hide
2674      */
2675    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2676
2677    /**
2678      * Mask for use with private flags indicating bits used for text alignment.
2679      * @hide
2680      */
2681    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2682
2683    /**
2684     * Array of text direction flags for mapping attribute "textAlignment" to correct
2685     * flag value.
2686     * @hide
2687     */
2688    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2689            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2690            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2691            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2692            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2693            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2694            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2695            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2696    };
2697
2698    /**
2699     * Indicates whether the view text alignment has been resolved.
2700     * @hide
2701     */
2702    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2703
2704    /**
2705     * Bit shift to get the resolved text alignment.
2706     * @hide
2707     */
2708    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2709
2710    /**
2711     * Mask for use with private flags indicating bits used for text alignment.
2712     * @hide
2713     */
2714    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2715            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2716
2717    /**
2718     * Indicates whether if the view text alignment has been resolved to gravity
2719     */
2720    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2721            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2722
2723    // Accessiblity constants for mPrivateFlags2
2724
2725    /**
2726     * Shift for the bits in {@link #mPrivateFlags2} related to the
2727     * "importantForAccessibility" attribute.
2728     */
2729    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2730
2731    /**
2732     * Automatically determine whether a view is important for accessibility.
2733     */
2734    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2735
2736    /**
2737     * The view is important for accessibility.
2738     */
2739    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2740
2741    /**
2742     * The view is not important for accessibility.
2743     */
2744    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2745
2746    /**
2747     * The view is not important for accessibility, nor are any of its
2748     * descendant views.
2749     */
2750    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2751
2752    /**
2753     * The default whether the view is important for accessibility.
2754     */
2755    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2756
2757    /**
2758     * Mask for obtaining the bits which specify how to determine
2759     * whether a view is important for accessibility.
2760     */
2761    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2762        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2763        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2764        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2765
2766    /**
2767     * Shift for the bits in {@link #mPrivateFlags2} related to the
2768     * "accessibilityLiveRegion" attribute.
2769     */
2770    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2771
2772    /**
2773     * Live region mode specifying that accessibility services should not
2774     * automatically announce changes to this view. This is the default live
2775     * region mode for most views.
2776     * <p>
2777     * Use with {@link #setAccessibilityLiveRegion(int)}.
2778     */
2779    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2780
2781    /**
2782     * Live region mode specifying that accessibility services should announce
2783     * changes to this view.
2784     * <p>
2785     * Use with {@link #setAccessibilityLiveRegion(int)}.
2786     */
2787    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2788
2789    /**
2790     * Live region mode specifying that accessibility services should interrupt
2791     * ongoing speech to immediately announce changes to this view.
2792     * <p>
2793     * Use with {@link #setAccessibilityLiveRegion(int)}.
2794     */
2795    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2796
2797    /**
2798     * The default whether the view is important for accessibility.
2799     */
2800    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2801
2802    /**
2803     * Mask for obtaining the bits which specify a view's accessibility live
2804     * region mode.
2805     */
2806    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2807            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2808            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2809
2810    /**
2811     * Flag indicating whether a view has accessibility focus.
2812     */
2813    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2814
2815    /**
2816     * Flag whether the accessibility state of the subtree rooted at this view changed.
2817     */
2818    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2819
2820    /**
2821     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2822     * is used to check whether later changes to the view's transform should invalidate the
2823     * view to force the quickReject test to run again.
2824     */
2825    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2826
2827    /**
2828     * Flag indicating that start/end padding has been resolved into left/right padding
2829     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2830     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2831     * during measurement. In some special cases this is required such as when an adapter-based
2832     * view measures prospective children without attaching them to a window.
2833     */
2834    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2835
2836    /**
2837     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2838     */
2839    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2840
2841    /**
2842     * Indicates that the view is tracking some sort of transient state
2843     * that the app should not need to be aware of, but that the framework
2844     * should take special care to preserve.
2845     */
2846    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2847
2848    /**
2849     * Group of bits indicating that RTL properties resolution is done.
2850     */
2851    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2852            PFLAG2_TEXT_DIRECTION_RESOLVED |
2853            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2854            PFLAG2_PADDING_RESOLVED |
2855            PFLAG2_DRAWABLE_RESOLVED;
2856
2857    // There are a couple of flags left in mPrivateFlags2
2858
2859    /* End of masks for mPrivateFlags2 */
2860
2861    /**
2862     * Masks for mPrivateFlags3, as generated by dumpFlags():
2863     *
2864     * |-------|-------|-------|-------|
2865     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2866     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2867     *                               1   PFLAG3_IS_LAID_OUT
2868     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2869     *                             1     PFLAG3_CALLED_SUPER
2870     *                            1      PFLAG3_APPLYING_INSETS
2871     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2872     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2873     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2874     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2875     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2876     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2877     *                     1             PFLAG3_SCROLL_INDICATOR_START
2878     *                    1              PFLAG3_SCROLL_INDICATOR_END
2879     *                   1               PFLAG3_ASSIST_BLOCKED
2880     *                  1                PFLAG3_CLUSTER
2881     *                 1                 PFLAG3_IS_AUTOFILLED
2882     *                1                  PFLAG3_FINGER_DOWN
2883     *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2884     *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
2885     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2886     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2887     *        1                          PFLAG3_TEMPORARY_DETACH
2888     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2889     *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
2890     * |-------|-------|-------|-------|
2891     */
2892
2893    /**
2894     * Flag indicating that view has a transform animation set on it. This is used to track whether
2895     * an animation is cleared between successive frames, in order to tell the associated
2896     * DisplayList to clear its animation matrix.
2897     */
2898    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2899
2900    /**
2901     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2902     * animation is cleared between successive frames, in order to tell the associated
2903     * DisplayList to restore its alpha value.
2904     */
2905    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2906
2907    /**
2908     * Flag indicating that the view has been through at least one layout since it
2909     * was last attached to a window.
2910     */
2911    static final int PFLAG3_IS_LAID_OUT = 0x4;
2912
2913    /**
2914     * Flag indicating that a call to measure() was skipped and should be done
2915     * instead when layout() is invoked.
2916     */
2917    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2918
2919    /**
2920     * Flag indicating that an overridden method correctly called down to
2921     * the superclass implementation as required by the API spec.
2922     */
2923    static final int PFLAG3_CALLED_SUPER = 0x10;
2924
2925    /**
2926     * Flag indicating that we're in the process of applying window insets.
2927     */
2928    static final int PFLAG3_APPLYING_INSETS = 0x20;
2929
2930    /**
2931     * Flag indicating that we're in the process of fitting system windows using the old method.
2932     */
2933    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2934
2935    /**
2936     * Flag indicating that nested scrolling is enabled for this view.
2937     * The view will optionally cooperate with views up its parent chain to allow for
2938     * integrated nested scrolling along the same axis.
2939     */
2940    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2941
2942    /**
2943     * Flag indicating that the bottom scroll indicator should be displayed
2944     * when this view can scroll up.
2945     */
2946    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2947
2948    /**
2949     * Flag indicating that the bottom scroll indicator should be displayed
2950     * when this view can scroll down.
2951     */
2952    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2953
2954    /**
2955     * Flag indicating that the left scroll indicator should be displayed
2956     * when this view can scroll left.
2957     */
2958    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2959
2960    /**
2961     * Flag indicating that the right scroll indicator should be displayed
2962     * when this view can scroll right.
2963     */
2964    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2965
2966    /**
2967     * Flag indicating that the start scroll indicator should be displayed
2968     * when this view can scroll in the start direction.
2969     */
2970    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2971
2972    /**
2973     * Flag indicating that the end scroll indicator should be displayed
2974     * when this view can scroll in the end direction.
2975     */
2976    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2977
2978    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2979
2980    static final int SCROLL_INDICATORS_NONE = 0x0000;
2981
2982    /**
2983     * Mask for use with setFlags indicating bits used for indicating which
2984     * scroll indicators are enabled.
2985     */
2986    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2987            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2988            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2989            | PFLAG3_SCROLL_INDICATOR_END;
2990
2991    /**
2992     * Left-shift required to translate between public scroll indicator flags
2993     * and internal PFLAGS3 flags. When used as a right-shift, translates
2994     * PFLAGS3 flags to public flags.
2995     */
2996    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2997
2998    /** @hide */
2999    @Retention(RetentionPolicy.SOURCE)
3000    @IntDef(flag = true,
3001            value = {
3002                    SCROLL_INDICATOR_TOP,
3003                    SCROLL_INDICATOR_BOTTOM,
3004                    SCROLL_INDICATOR_LEFT,
3005                    SCROLL_INDICATOR_RIGHT,
3006                    SCROLL_INDICATOR_START,
3007                    SCROLL_INDICATOR_END,
3008            })
3009    public @interface ScrollIndicators {}
3010
3011    /**
3012     * Scroll indicator direction for the top edge of the view.
3013     *
3014     * @see #setScrollIndicators(int)
3015     * @see #setScrollIndicators(int, int)
3016     * @see #getScrollIndicators()
3017     */
3018    public static final int SCROLL_INDICATOR_TOP =
3019            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3020
3021    /**
3022     * Scroll indicator direction for the bottom edge of the view.
3023     *
3024     * @see #setScrollIndicators(int)
3025     * @see #setScrollIndicators(int, int)
3026     * @see #getScrollIndicators()
3027     */
3028    public static final int SCROLL_INDICATOR_BOTTOM =
3029            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3030
3031    /**
3032     * Scroll indicator direction for the left edge of the view.
3033     *
3034     * @see #setScrollIndicators(int)
3035     * @see #setScrollIndicators(int, int)
3036     * @see #getScrollIndicators()
3037     */
3038    public static final int SCROLL_INDICATOR_LEFT =
3039            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3040
3041    /**
3042     * Scroll indicator direction for the right edge of the view.
3043     *
3044     * @see #setScrollIndicators(int)
3045     * @see #setScrollIndicators(int, int)
3046     * @see #getScrollIndicators()
3047     */
3048    public static final int SCROLL_INDICATOR_RIGHT =
3049            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3050
3051    /**
3052     * Scroll indicator direction for the starting edge of the view.
3053     * <p>
3054     * Resolved according to the view's layout direction, see
3055     * {@link #getLayoutDirection()} for more information.
3056     *
3057     * @see #setScrollIndicators(int)
3058     * @see #setScrollIndicators(int, int)
3059     * @see #getScrollIndicators()
3060     */
3061    public static final int SCROLL_INDICATOR_START =
3062            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3063
3064    /**
3065     * Scroll indicator direction for the ending edge of the view.
3066     * <p>
3067     * Resolved according to the view's layout direction, see
3068     * {@link #getLayoutDirection()} for more information.
3069     *
3070     * @see #setScrollIndicators(int)
3071     * @see #setScrollIndicators(int, int)
3072     * @see #getScrollIndicators()
3073     */
3074    public static final int SCROLL_INDICATOR_END =
3075            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3076
3077    /**
3078     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3079     * into this view.<p>
3080     */
3081    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3082
3083    /**
3084     * Flag indicating that the view is a root of a keyboard navigation cluster.
3085     *
3086     * @see #isKeyboardNavigationCluster()
3087     * @see #setKeyboardNavigationCluster(boolean)
3088     */
3089    private static final int PFLAG3_CLUSTER = 0x8000;
3090
3091    /**
3092     * Flag indicating that the view is autofilled
3093     *
3094     * @see #isAutofilled()
3095     * @see #setAutofilled(boolean)
3096     */
3097    private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3098
3099    /**
3100     * Indicates that the user is currently touching the screen.
3101     * Currently used for the tooltip positioning only.
3102     */
3103    private static final int PFLAG3_FINGER_DOWN = 0x20000;
3104
3105    /**
3106     * Flag indicating that this view is the default-focus view.
3107     *
3108     * @see #isFocusedByDefault()
3109     * @see #setFocusedByDefault(boolean)
3110     */
3111    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3112
3113    /**
3114     * Shift for the bits in {@link #mPrivateFlags3} related to the
3115     * "importantForAutofill" attribute.
3116     */
3117    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3118
3119    /**
3120     * Mask for obtaining the bits which specify how to determine
3121     * whether a view is important for autofill.
3122     */
3123    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3124            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3125            | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3126            | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3127            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3128
3129    /**
3130     * Whether this view has rendered elements that overlap (see {@link
3131     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3132     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3133     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3134     * determined by whatever {@link #hasOverlappingRendering()} returns.
3135     */
3136    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3137
3138    /**
3139     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3140     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3141     */
3142    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3143
3144    /**
3145     * Flag indicating that the view is temporarily detached from the parent view.
3146     *
3147     * @see #onStartTemporaryDetach()
3148     * @see #onFinishTemporaryDetach()
3149     */
3150    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3151
3152    /**
3153     * Flag indicating that the view does not wish to be revealed within its parent
3154     * hierarchy when it gains focus. Expressed in the negative since the historical
3155     * default behavior is to reveal on focus; this flag suppresses that behavior.
3156     *
3157     * @see #setRevealOnFocusHint(boolean)
3158     * @see #getRevealOnFocusHint()
3159     */
3160    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3161
3162    /**
3163     * Flag indicating that when layout is completed we should notify
3164     * that the view was entered for autofill purposes. To minimize
3165     * showing autofill for views not visible to the user we evaluate
3166     * user visibility which cannot be done until the view is laid out.
3167     */
3168    static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3169
3170    /* End of masks for mPrivateFlags3 */
3171
3172    /**
3173     * Always allow a user to over-scroll this view, provided it is a
3174     * view that can scroll.
3175     *
3176     * @see #getOverScrollMode()
3177     * @see #setOverScrollMode(int)
3178     */
3179    public static final int OVER_SCROLL_ALWAYS = 0;
3180
3181    /**
3182     * Allow a user to over-scroll this view only if the content is large
3183     * enough to meaningfully scroll, provided it is a view that can scroll.
3184     *
3185     * @see #getOverScrollMode()
3186     * @see #setOverScrollMode(int)
3187     */
3188    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3189
3190    /**
3191     * Never allow a user to over-scroll this view.
3192     *
3193     * @see #getOverScrollMode()
3194     * @see #setOverScrollMode(int)
3195     */
3196    public static final int OVER_SCROLL_NEVER = 2;
3197
3198    /**
3199     * Special constant for {@link #setSystemUiVisibility(int)}: View has
3200     * requested the system UI (status bar) to be visible (the default).
3201     *
3202     * @see #setSystemUiVisibility(int)
3203     */
3204    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3205
3206    /**
3207     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3208     * system UI to enter an unobtrusive "low profile" mode.
3209     *
3210     * <p>This is for use in games, book readers, video players, or any other
3211     * "immersive" application where the usual system chrome is deemed too distracting.
3212     *
3213     * <p>In low profile mode, the status bar and/or navigation icons may dim.
3214     *
3215     * @see #setSystemUiVisibility(int)
3216     */
3217    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3218
3219    /**
3220     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3221     * system navigation be temporarily hidden.
3222     *
3223     * <p>This is an even less obtrusive state than that called for by
3224     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3225     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3226     * those to disappear. This is useful (in conjunction with the
3227     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3228     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3229     * window flags) for displaying content using every last pixel on the display.
3230     *
3231     * <p>There is a limitation: because navigation controls are so important, the least user
3232     * interaction will cause them to reappear immediately.  When this happens, both
3233     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3234     * so that both elements reappear at the same time.
3235     *
3236     * @see #setSystemUiVisibility(int)
3237     */
3238    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3239
3240    /**
3241     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3242     * into the normal fullscreen mode so that its content can take over the screen
3243     * while still allowing the user to interact with the application.
3244     *
3245     * <p>This has the same visual effect as
3246     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3247     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3248     * meaning that non-critical screen decorations (such as the status bar) will be
3249     * hidden while the user is in the View's window, focusing the experience on
3250     * that content.  Unlike the window flag, if you are using ActionBar in
3251     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3252     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3253     * hide the action bar.
3254     *
3255     * <p>This approach to going fullscreen is best used over the window flag when
3256     * it is a transient state -- that is, the application does this at certain
3257     * points in its user interaction where it wants to allow the user to focus
3258     * on content, but not as a continuous state.  For situations where the application
3259     * would like to simply stay full screen the entire time (such as a game that
3260     * wants to take over the screen), the
3261     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3262     * is usually a better approach.  The state set here will be removed by the system
3263     * in various situations (such as the user moving to another application) like
3264     * the other system UI states.
3265     *
3266     * <p>When using this flag, the application should provide some easy facility
3267     * for the user to go out of it.  A common example would be in an e-book
3268     * reader, where tapping on the screen brings back whatever screen and UI
3269     * decorations that had been hidden while the user was immersed in reading
3270     * the book.
3271     *
3272     * @see #setSystemUiVisibility(int)
3273     */
3274    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3275
3276    /**
3277     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3278     * flags, we would like a stable view of the content insets given to
3279     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3280     * will always represent the worst case that the application can expect
3281     * as a continuous state.  In the stock Android UI this is the space for
3282     * the system bar, nav bar, and status bar, but not more transient elements
3283     * such as an input method.
3284     *
3285     * The stable layout your UI sees is based on the system UI modes you can
3286     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3287     * then you will get a stable layout for changes of the
3288     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3289     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3290     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3291     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3292     * with a stable layout.  (Note that you should avoid using
3293     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3294     *
3295     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3296     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3297     * then a hidden status bar will be considered a "stable" state for purposes
3298     * here.  This allows your UI to continually hide the status bar, while still
3299     * using the system UI flags to hide the action bar while still retaining
3300     * a stable layout.  Note that changing the window fullscreen flag will never
3301     * provide a stable layout for a clean transition.
3302     *
3303     * <p>If you are using ActionBar in
3304     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3305     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3306     * insets it adds to those given to the application.
3307     */
3308    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3309
3310    /**
3311     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3312     * to be laid out as if it has requested
3313     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3314     * allows it to avoid artifacts when switching in and out of that mode, at
3315     * the expense that some of its user interface may be covered by screen
3316     * decorations when they are shown.  You can perform layout of your inner
3317     * UI elements to account for the navigation system UI through the
3318     * {@link #fitSystemWindows(Rect)} method.
3319     */
3320    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3321
3322    /**
3323     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3324     * to be laid out as if it has requested
3325     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3326     * allows it to avoid artifacts when switching in and out of that mode, at
3327     * the expense that some of its user interface may be covered by screen
3328     * decorations when they are shown.  You can perform layout of your inner
3329     * UI elements to account for non-fullscreen system UI through the
3330     * {@link #fitSystemWindows(Rect)} method.
3331     */
3332    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3333
3334    /**
3335     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3336     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3337     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3338     * user interaction.
3339     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3340     * has an effect when used in combination with that flag.</p>
3341     */
3342    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3343
3344    /**
3345     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3346     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3347     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3348     * experience while also hiding the system bars.  If this flag is not set,
3349     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3350     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3351     * if the user swipes from the top of the screen.
3352     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3353     * system gestures, such as swiping from the top of the screen.  These transient system bars
3354     * will overlay app’s content, may have some degree of transparency, and will automatically
3355     * hide after a short timeout.
3356     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3357     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3358     * with one or both of those flags.</p>
3359     */
3360    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3361
3362    /**
3363     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3364     * is compatible with light status bar backgrounds.
3365     *
3366     * <p>For this to take effect, the window must request
3367     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3368     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3369     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3370     *         FLAG_TRANSLUCENT_STATUS}.
3371     *
3372     * @see android.R.attr#windowLightStatusBar
3373     */
3374    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3375
3376    /**
3377     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3378     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3379     */
3380    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3381
3382    /**
3383     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3384     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3385     */
3386    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3387
3388    /**
3389     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3390     * that is compatible with light navigation bar backgrounds.
3391     *
3392     * <p>For this to take effect, the window must request
3393     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3394     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3395     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3396     *         FLAG_TRANSLUCENT_NAVIGATION}.
3397     */
3398    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3399
3400    /**
3401     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3402     */
3403    @Deprecated
3404    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3405
3406    /**
3407     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3408     */
3409    @Deprecated
3410    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3411
3412    /**
3413     * @hide
3414     *
3415     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3416     * out of the public fields to keep the undefined bits out of the developer's way.
3417     *
3418     * Flag to make the status bar not expandable.  Unless you also
3419     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3420     */
3421    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3422
3423    /**
3424     * @hide
3425     *
3426     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3427     * out of the public fields to keep the undefined bits out of the developer's way.
3428     *
3429     * Flag to hide notification icons and scrolling ticker text.
3430     */
3431    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3432
3433    /**
3434     * @hide
3435     *
3436     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3437     * out of the public fields to keep the undefined bits out of the developer's way.
3438     *
3439     * Flag to disable incoming notification alerts.  This will not block
3440     * icons, but it will block sound, vibrating and other visual or aural notifications.
3441     */
3442    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3443
3444    /**
3445     * @hide
3446     *
3447     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3448     * out of the public fields to keep the undefined bits out of the developer's way.
3449     *
3450     * Flag to hide only the scrolling ticker.  Note that
3451     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3452     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3453     */
3454    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3455
3456    /**
3457     * @hide
3458     *
3459     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3460     * out of the public fields to keep the undefined bits out of the developer's way.
3461     *
3462     * Flag to hide the center system info area.
3463     */
3464    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3465
3466    /**
3467     * @hide
3468     *
3469     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3470     * out of the public fields to keep the undefined bits out of the developer's way.
3471     *
3472     * Flag to hide only the home button.  Don't use this
3473     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3474     */
3475    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3476
3477    /**
3478     * @hide
3479     *
3480     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3481     * out of the public fields to keep the undefined bits out of the developer's way.
3482     *
3483     * Flag to hide only the back button. Don't use this
3484     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3485     */
3486    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3487
3488    /**
3489     * @hide
3490     *
3491     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3492     * out of the public fields to keep the undefined bits out of the developer's way.
3493     *
3494     * Flag to hide only the clock.  You might use this if your activity has
3495     * its own clock making the status bar's clock redundant.
3496     */
3497    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3498
3499    /**
3500     * @hide
3501     *
3502     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3503     * out of the public fields to keep the undefined bits out of the developer's way.
3504     *
3505     * Flag to hide only the recent apps button. Don't use this
3506     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3507     */
3508    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3509
3510    /**
3511     * @hide
3512     *
3513     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3514     * out of the public fields to keep the undefined bits out of the developer's way.
3515     *
3516     * Flag to disable the global search gesture. Don't use this
3517     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3518     */
3519    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3520
3521    /**
3522     * @hide
3523     *
3524     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3525     * out of the public fields to keep the undefined bits out of the developer's way.
3526     *
3527     * Flag to specify that the status bar is displayed in transient mode.
3528     */
3529    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3530
3531    /**
3532     * @hide
3533     *
3534     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3535     * out of the public fields to keep the undefined bits out of the developer's way.
3536     *
3537     * Flag to specify that the navigation bar is displayed in transient mode.
3538     */
3539    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3540
3541    /**
3542     * @hide
3543     *
3544     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3545     * out of the public fields to keep the undefined bits out of the developer's way.
3546     *
3547     * Flag to specify that the hidden status bar would like to be shown.
3548     */
3549    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3550
3551    /**
3552     * @hide
3553     *
3554     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3555     * out of the public fields to keep the undefined bits out of the developer's way.
3556     *
3557     * Flag to specify that the hidden navigation bar would like to be shown.
3558     */
3559    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3560
3561    /**
3562     * @hide
3563     *
3564     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3565     * out of the public fields to keep the undefined bits out of the developer's way.
3566     *
3567     * Flag to specify that the status bar is displayed in translucent mode.
3568     */
3569    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3570
3571    /**
3572     * @hide
3573     *
3574     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3575     * out of the public fields to keep the undefined bits out of the developer's way.
3576     *
3577     * Flag to specify that the navigation bar is displayed in translucent mode.
3578     */
3579    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3580
3581    /**
3582     * @hide
3583     *
3584     * Makes navigation bar transparent (but not the status bar).
3585     */
3586    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3587
3588    /**
3589     * @hide
3590     *
3591     * Makes status bar transparent (but not the navigation bar).
3592     */
3593    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3594
3595    /**
3596     * @hide
3597     *
3598     * Makes both status bar and navigation bar transparent.
3599     */
3600    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3601            | STATUS_BAR_TRANSPARENT;
3602
3603    /**
3604     * @hide
3605     */
3606    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3607
3608    /**
3609     * These are the system UI flags that can be cleared by events outside
3610     * of an application.  Currently this is just the ability to tap on the
3611     * screen while hiding the navigation bar to have it return.
3612     * @hide
3613     */
3614    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3615            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3616            | SYSTEM_UI_FLAG_FULLSCREEN;
3617
3618    /**
3619     * Flags that can impact the layout in relation to system UI.
3620     */
3621    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3622            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3623            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3624
3625    /** @hide */
3626    @IntDef(flag = true,
3627            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3628    @Retention(RetentionPolicy.SOURCE)
3629    public @interface FindViewFlags {}
3630
3631    /**
3632     * Find views that render the specified text.
3633     *
3634     * @see #findViewsWithText(ArrayList, CharSequence, int)
3635     */
3636    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3637
3638    /**
3639     * Find find views that contain the specified content description.
3640     *
3641     * @see #findViewsWithText(ArrayList, CharSequence, int)
3642     */
3643    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3644
3645    /**
3646     * Find views that contain {@link AccessibilityNodeProvider}. Such
3647     * a View is a root of virtual view hierarchy and may contain the searched
3648     * text. If this flag is set Views with providers are automatically
3649     * added and it is a responsibility of the client to call the APIs of
3650     * the provider to determine whether the virtual tree rooted at this View
3651     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3652     * representing the virtual views with this text.
3653     *
3654     * @see #findViewsWithText(ArrayList, CharSequence, int)
3655     *
3656     * @hide
3657     */
3658    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3659
3660    /**
3661     * The undefined cursor position.
3662     *
3663     * @hide
3664     */
3665    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3666
3667    /**
3668     * Indicates that the screen has changed state and is now off.
3669     *
3670     * @see #onScreenStateChanged(int)
3671     */
3672    public static final int SCREEN_STATE_OFF = 0x0;
3673
3674    /**
3675     * Indicates that the screen has changed state and is now on.
3676     *
3677     * @see #onScreenStateChanged(int)
3678     */
3679    public static final int SCREEN_STATE_ON = 0x1;
3680
3681    /**
3682     * Indicates no axis of view scrolling.
3683     */
3684    public static final int SCROLL_AXIS_NONE = 0;
3685
3686    /**
3687     * Indicates scrolling along the horizontal axis.
3688     */
3689    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3690
3691    /**
3692     * Indicates scrolling along the vertical axis.
3693     */
3694    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3695
3696    /**
3697     * Controls the over-scroll mode for this view.
3698     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3699     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3700     * and {@link #OVER_SCROLL_NEVER}.
3701     */
3702    private int mOverScrollMode;
3703
3704    /**
3705     * The parent this view is attached to.
3706     * {@hide}
3707     *
3708     * @see #getParent()
3709     */
3710    protected ViewParent mParent;
3711
3712    /**
3713     * {@hide}
3714     */
3715    AttachInfo mAttachInfo;
3716
3717    /**
3718     * {@hide}
3719     */
3720    @ViewDebug.ExportedProperty(flagMapping = {
3721        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3722                name = "FORCE_LAYOUT"),
3723        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3724                name = "LAYOUT_REQUIRED"),
3725        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3726            name = "DRAWING_CACHE_INVALID", outputIf = false),
3727        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3728        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3729        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3730        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3731    }, formatToHexString = true)
3732
3733    /* @hide */
3734    public int mPrivateFlags;
3735    int mPrivateFlags2;
3736    int mPrivateFlags3;
3737
3738    /**
3739     * This view's request for the visibility of the status bar.
3740     * @hide
3741     */
3742    @ViewDebug.ExportedProperty(flagMapping = {
3743        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3744                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3745                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3746        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3747                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3748                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3749        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3750                                equals = SYSTEM_UI_FLAG_VISIBLE,
3751                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3752    }, formatToHexString = true)
3753    int mSystemUiVisibility;
3754
3755    /**
3756     * Reference count for transient state.
3757     * @see #setHasTransientState(boolean)
3758     */
3759    int mTransientStateCount = 0;
3760
3761    /**
3762     * Count of how many windows this view has been attached to.
3763     */
3764    int mWindowAttachCount;
3765
3766    /**
3767     * The layout parameters associated with this view and used by the parent
3768     * {@link android.view.ViewGroup} to determine how this view should be
3769     * laid out.
3770     * {@hide}
3771     */
3772    protected ViewGroup.LayoutParams mLayoutParams;
3773
3774    /**
3775     * The view flags hold various views states.
3776     * {@hide}
3777     */
3778    @ViewDebug.ExportedProperty(formatToHexString = true)
3779    int mViewFlags;
3780
3781    static class TransformationInfo {
3782        /**
3783         * The transform matrix for the View. This transform is calculated internally
3784         * based on the translation, rotation, and scale properties.
3785         *
3786         * Do *not* use this variable directly; instead call getMatrix(), which will
3787         * load the value from the View's RenderNode.
3788         */
3789        private final Matrix mMatrix = new Matrix();
3790
3791        /**
3792         * The inverse transform matrix for the View. This transform is calculated
3793         * internally based on the translation, rotation, and scale properties.
3794         *
3795         * Do *not* use this variable directly; instead call getInverseMatrix(),
3796         * which will load the value from the View's RenderNode.
3797         */
3798        private Matrix mInverseMatrix;
3799
3800        /**
3801         * The opacity of the View. This is a value from 0 to 1, where 0 means
3802         * completely transparent and 1 means completely opaque.
3803         */
3804        @ViewDebug.ExportedProperty
3805        float mAlpha = 1f;
3806
3807        /**
3808         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3809         * property only used by transitions, which is composited with the other alpha
3810         * values to calculate the final visual alpha value.
3811         */
3812        float mTransitionAlpha = 1f;
3813    }
3814
3815    /** @hide */
3816    public TransformationInfo mTransformationInfo;
3817
3818    /**
3819     * Current clip bounds. to which all drawing of this view are constrained.
3820     */
3821    Rect mClipBounds = null;
3822
3823    private boolean mLastIsOpaque;
3824
3825    /**
3826     * The distance in pixels from the left edge of this view's parent
3827     * to the left edge of this view.
3828     * {@hide}
3829     */
3830    @ViewDebug.ExportedProperty(category = "layout")
3831    protected int mLeft;
3832    /**
3833     * The distance in pixels from the left edge of this view's parent
3834     * to the right edge of this view.
3835     * {@hide}
3836     */
3837    @ViewDebug.ExportedProperty(category = "layout")
3838    protected int mRight;
3839    /**
3840     * The distance in pixels from the top edge of this view's parent
3841     * to the top edge of this view.
3842     * {@hide}
3843     */
3844    @ViewDebug.ExportedProperty(category = "layout")
3845    protected int mTop;
3846    /**
3847     * The distance in pixels from the top edge of this view's parent
3848     * to the bottom edge of this view.
3849     * {@hide}
3850     */
3851    @ViewDebug.ExportedProperty(category = "layout")
3852    protected int mBottom;
3853
3854    /**
3855     * The offset, in pixels, by which the content of this view is scrolled
3856     * horizontally.
3857     * {@hide}
3858     */
3859    @ViewDebug.ExportedProperty(category = "scrolling")
3860    protected int mScrollX;
3861    /**
3862     * The offset, in pixels, by which the content of this view is scrolled
3863     * vertically.
3864     * {@hide}
3865     */
3866    @ViewDebug.ExportedProperty(category = "scrolling")
3867    protected int mScrollY;
3868
3869    /**
3870     * The left padding in pixels, that is the distance in pixels between the
3871     * left edge of this view and the left edge of its content.
3872     * {@hide}
3873     */
3874    @ViewDebug.ExportedProperty(category = "padding")
3875    protected int mPaddingLeft = 0;
3876    /**
3877     * The right padding in pixels, that is the distance in pixels between the
3878     * right edge of this view and the right edge of its content.
3879     * {@hide}
3880     */
3881    @ViewDebug.ExportedProperty(category = "padding")
3882    protected int mPaddingRight = 0;
3883    /**
3884     * The top padding in pixels, that is the distance in pixels between the
3885     * top edge of this view and the top edge of its content.
3886     * {@hide}
3887     */
3888    @ViewDebug.ExportedProperty(category = "padding")
3889    protected int mPaddingTop;
3890    /**
3891     * The bottom padding in pixels, that is the distance in pixels between the
3892     * bottom edge of this view and the bottom edge of its content.
3893     * {@hide}
3894     */
3895    @ViewDebug.ExportedProperty(category = "padding")
3896    protected int mPaddingBottom;
3897
3898    /**
3899     * The layout insets in pixels, that is the distance in pixels between the
3900     * visible edges of this view its bounds.
3901     */
3902    private Insets mLayoutInsets;
3903
3904    /**
3905     * Briefly describes the view and is primarily used for accessibility support.
3906     */
3907    private CharSequence mContentDescription;
3908
3909    /**
3910     * Specifies the id of a view for which this view serves as a label for
3911     * accessibility purposes.
3912     */
3913    private int mLabelForId = View.NO_ID;
3914
3915    /**
3916     * Predicate for matching labeled view id with its label for
3917     * accessibility purposes.
3918     */
3919    private MatchLabelForPredicate mMatchLabelForPredicate;
3920
3921    /**
3922     * Specifies a view before which this one is visited in accessibility traversal.
3923     */
3924    private int mAccessibilityTraversalBeforeId = NO_ID;
3925
3926    /**
3927     * Specifies a view after which this one is visited in accessibility traversal.
3928     */
3929    private int mAccessibilityTraversalAfterId = NO_ID;
3930
3931    /**
3932     * Predicate for matching a view by its id.
3933     */
3934    private MatchIdPredicate mMatchIdPredicate;
3935
3936    /**
3937     * Cache the paddingRight set by the user to append to the scrollbar's size.
3938     *
3939     * @hide
3940     */
3941    @ViewDebug.ExportedProperty(category = "padding")
3942    protected int mUserPaddingRight;
3943
3944    /**
3945     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3946     *
3947     * @hide
3948     */
3949    @ViewDebug.ExportedProperty(category = "padding")
3950    protected int mUserPaddingBottom;
3951
3952    /**
3953     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3954     *
3955     * @hide
3956     */
3957    @ViewDebug.ExportedProperty(category = "padding")
3958    protected int mUserPaddingLeft;
3959
3960    /**
3961     * Cache the paddingStart set by the user to append to the scrollbar's size.
3962     *
3963     */
3964    @ViewDebug.ExportedProperty(category = "padding")
3965    int mUserPaddingStart;
3966
3967    /**
3968     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3969     *
3970     */
3971    @ViewDebug.ExportedProperty(category = "padding")
3972    int mUserPaddingEnd;
3973
3974    /**
3975     * Cache initial left padding.
3976     *
3977     * @hide
3978     */
3979    int mUserPaddingLeftInitial;
3980
3981    /**
3982     * Cache initial right padding.
3983     *
3984     * @hide
3985     */
3986    int mUserPaddingRightInitial;
3987
3988    /**
3989     * Default undefined padding
3990     */
3991    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3992
3993    /**
3994     * Cache if a left padding has been defined
3995     */
3996    private boolean mLeftPaddingDefined = false;
3997
3998    /**
3999     * Cache if a right padding has been defined
4000     */
4001    private boolean mRightPaddingDefined = false;
4002
4003    /**
4004     * @hide
4005     */
4006    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
4007    /**
4008     * @hide
4009     */
4010    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
4011
4012    private LongSparseLongArray mMeasureCache;
4013
4014    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
4015    private Drawable mBackground;
4016    private TintInfo mBackgroundTint;
4017
4018    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
4019    private ForegroundInfo mForegroundInfo;
4020
4021    private Drawable mScrollIndicatorDrawable;
4022
4023    /**
4024     * RenderNode used for backgrounds.
4025     * <p>
4026     * When non-null and valid, this is expected to contain an up-to-date copy
4027     * of the background drawable. It is cleared on temporary detach, and reset
4028     * on cleanup.
4029     */
4030    private RenderNode mBackgroundRenderNode;
4031
4032    private int mBackgroundResource;
4033    private boolean mBackgroundSizeChanged;
4034
4035    /** The default focus highlight.
4036     * @see #mDefaultFocusHighlightEnabled
4037     * @see Drawable#hasFocusStateSpecified()
4038     */
4039    private Drawable mDefaultFocusHighlight;
4040    private Drawable mDefaultFocusHighlightCache;
4041    private boolean mDefaultFocusHighlightSizeChanged;
4042    /**
4043     * True if the default focus highlight is needed on the target device.
4044     */
4045    private static boolean sUseDefaultFocusHighlight;
4046
4047    private String mTransitionName;
4048
4049    static class TintInfo {
4050        ColorStateList mTintList;
4051        PorterDuff.Mode mTintMode;
4052        boolean mHasTintMode;
4053        boolean mHasTintList;
4054    }
4055
4056    private static class ForegroundInfo {
4057        private Drawable mDrawable;
4058        private TintInfo mTintInfo;
4059        private int mGravity = Gravity.FILL;
4060        private boolean mInsidePadding = true;
4061        private boolean mBoundsChanged = true;
4062        private final Rect mSelfBounds = new Rect();
4063        private final Rect mOverlayBounds = new Rect();
4064    }
4065
4066    static class ListenerInfo {
4067        /**
4068         * Listener used to dispatch focus change events.
4069         * This field should be made private, so it is hidden from the SDK.
4070         * {@hide}
4071         */
4072        protected OnFocusChangeListener mOnFocusChangeListener;
4073
4074        /**
4075         * Listeners for layout change events.
4076         */
4077        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4078
4079        protected OnScrollChangeListener mOnScrollChangeListener;
4080
4081        /**
4082         * Listeners for attach events.
4083         */
4084        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4085
4086        /**
4087         * Listener used to dispatch click events.
4088         * This field should be made private, so it is hidden from the SDK.
4089         * {@hide}
4090         */
4091        public OnClickListener mOnClickListener;
4092
4093        /**
4094         * Listener used to dispatch long click events.
4095         * This field should be made private, so it is hidden from the SDK.
4096         * {@hide}
4097         */
4098        protected OnLongClickListener mOnLongClickListener;
4099
4100        /**
4101         * Listener used to dispatch context click events. This field should be made private, so it
4102         * is hidden from the SDK.
4103         * {@hide}
4104         */
4105        protected OnContextClickListener mOnContextClickListener;
4106
4107        /**
4108         * Listener used to build the context menu.
4109         * This field should be made private, so it is hidden from the SDK.
4110         * {@hide}
4111         */
4112        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4113
4114        private OnKeyListener mOnKeyListener;
4115
4116        private OnTouchListener mOnTouchListener;
4117
4118        private OnHoverListener mOnHoverListener;
4119
4120        private OnGenericMotionListener mOnGenericMotionListener;
4121
4122        private OnDragListener mOnDragListener;
4123
4124        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4125
4126        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4127
4128        OnCapturedPointerListener mOnCapturedPointerListener;
4129    }
4130
4131    ListenerInfo mListenerInfo;
4132
4133    private static class TooltipInfo {
4134        /**
4135         * Text to be displayed in a tooltip popup.
4136         */
4137        @Nullable
4138        CharSequence mTooltipText;
4139
4140        /**
4141         * View-relative position of the tooltip anchor point.
4142         */
4143        int mAnchorX;
4144        int mAnchorY;
4145
4146        /**
4147         * The tooltip popup.
4148         */
4149        @Nullable
4150        TooltipPopup mTooltipPopup;
4151
4152        /**
4153         * Set to true if the tooltip was shown as a result of a long click.
4154         */
4155        boolean mTooltipFromLongClick;
4156
4157        /**
4158         * Keep these Runnables so that they can be used to reschedule.
4159         */
4160        Runnable mShowTooltipRunnable;
4161        Runnable mHideTooltipRunnable;
4162    }
4163
4164    TooltipInfo mTooltipInfo;
4165
4166    // Temporary values used to hold (x,y) coordinates when delegating from the
4167    // two-arg performLongClick() method to the legacy no-arg version.
4168    private float mLongClickX = Float.NaN;
4169    private float mLongClickY = Float.NaN;
4170
4171    /**
4172     * The application environment this view lives in.
4173     * This field should be made private, so it is hidden from the SDK.
4174     * {@hide}
4175     */
4176    @ViewDebug.ExportedProperty(deepExport = true)
4177    protected Context mContext;
4178
4179    private final Resources mResources;
4180
4181    private ScrollabilityCache mScrollCache;
4182
4183    private int[] mDrawableState = null;
4184
4185    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4186
4187    /**
4188     * Animator that automatically runs based on state changes.
4189     */
4190    private StateListAnimator mStateListAnimator;
4191
4192    /**
4193     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4194     * the user may specify which view to go to next.
4195     */
4196    private int mNextFocusLeftId = View.NO_ID;
4197
4198    /**
4199     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4200     * the user may specify which view to go to next.
4201     */
4202    private int mNextFocusRightId = View.NO_ID;
4203
4204    /**
4205     * When this view has focus and the next focus is {@link #FOCUS_UP},
4206     * the user may specify which view to go to next.
4207     */
4208    private int mNextFocusUpId = View.NO_ID;
4209
4210    /**
4211     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4212     * the user may specify which view to go to next.
4213     */
4214    private int mNextFocusDownId = View.NO_ID;
4215
4216    /**
4217     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4218     * the user may specify which view to go to next.
4219     */
4220    int mNextFocusForwardId = View.NO_ID;
4221
4222    /**
4223     * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4224     *
4225     * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4226     */
4227    int mNextClusterForwardId = View.NO_ID;
4228
4229    /**
4230     * Whether this View should use a default focus highlight when it gets focused but doesn't
4231     * have {@link android.R.attr#state_focused} defined in its background.
4232     */
4233    boolean mDefaultFocusHighlightEnabled = true;
4234
4235    private CheckForLongPress mPendingCheckForLongPress;
4236    private CheckForTap mPendingCheckForTap = null;
4237    private PerformClick mPerformClick;
4238    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4239
4240    private UnsetPressedState mUnsetPressedState;
4241
4242    /**
4243     * Whether the long press's action has been invoked.  The tap's action is invoked on the
4244     * up event while a long press is invoked as soon as the long press duration is reached, so
4245     * a long press could be performed before the tap is checked, in which case the tap's action
4246     * should not be invoked.
4247     */
4248    private boolean mHasPerformedLongPress;
4249
4250    /**
4251     * Whether a context click button is currently pressed down. This is true when the stylus is
4252     * touching the screen and the primary button has been pressed, or if a mouse's right button is
4253     * pressed. This is false once the button is released or if the stylus has been lifted.
4254     */
4255    private boolean mInContextButtonPress;
4256
4257    /**
4258     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4259     * true after a stylus button press has occured, when the next up event should not be recognized
4260     * as a tap.
4261     */
4262    private boolean mIgnoreNextUpEvent;
4263
4264    /**
4265     * The minimum height of the view. We'll try our best to have the height
4266     * of this view to at least this amount.
4267     */
4268    @ViewDebug.ExportedProperty(category = "measurement")
4269    private int mMinHeight;
4270
4271    /**
4272     * The minimum width of the view. We'll try our best to have the width
4273     * of this view to at least this amount.
4274     */
4275    @ViewDebug.ExportedProperty(category = "measurement")
4276    private int mMinWidth;
4277
4278    /**
4279     * The delegate to handle touch events that are physically in this view
4280     * but should be handled by another view.
4281     */
4282    private TouchDelegate mTouchDelegate = null;
4283
4284    /**
4285     * Solid color to use as a background when creating the drawing cache. Enables
4286     * the cache to use 16 bit bitmaps instead of 32 bit.
4287     */
4288    private int mDrawingCacheBackgroundColor = 0;
4289
4290    /**
4291     * Special tree observer used when mAttachInfo is null.
4292     */
4293    private ViewTreeObserver mFloatingTreeObserver;
4294
4295    /**
4296     * Cache the touch slop from the context that created the view.
4297     */
4298    private int mTouchSlop;
4299
4300    /**
4301     * Object that handles automatic animation of view properties.
4302     */
4303    private ViewPropertyAnimator mAnimator = null;
4304
4305    /**
4306     * List of registered FrameMetricsObservers.
4307     */
4308    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4309
4310    /**
4311     * Flag indicating that a drag can cross window boundaries.  When
4312     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4313     * with this flag set, all visible applications with targetSdkVersion >=
4314     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4315     * in the drag operation and receive the dragged content.
4316     *
4317     * <p>If this is the only flag set, then the drag recipient will only have access to text data
4318     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4319     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4320     */
4321    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4322
4323    /**
4324     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4325     * request read access to the content URI(s) contained in the {@link ClipData} object.
4326     * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4327     */
4328    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4329
4330    /**
4331     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4332     * request write access to the content URI(s) contained in the {@link ClipData} object.
4333     * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4334     */
4335    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4336
4337    /**
4338     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4339     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4340     * reboots until explicitly revoked with
4341     * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4342     * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4343     */
4344    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4345            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4346
4347    /**
4348     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4349     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4350     * match against the original granted URI.
4351     * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4352     */
4353    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4354            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4355
4356    /**
4357     * Flag indicating that the drag shadow will be opaque.  When
4358     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4359     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4360     */
4361    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4362
4363    /**
4364     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4365     */
4366    private float mVerticalScrollFactor;
4367
4368    /**
4369     * Position of the vertical scroll bar.
4370     */
4371    private int mVerticalScrollbarPosition;
4372
4373    /**
4374     * Position the scroll bar at the default position as determined by the system.
4375     */
4376    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4377
4378    /**
4379     * Position the scroll bar along the left edge.
4380     */
4381    public static final int SCROLLBAR_POSITION_LEFT = 1;
4382
4383    /**
4384     * Position the scroll bar along the right edge.
4385     */
4386    public static final int SCROLLBAR_POSITION_RIGHT = 2;
4387
4388    /**
4389     * Indicates that the view does not have a layer.
4390     *
4391     * @see #getLayerType()
4392     * @see #setLayerType(int, android.graphics.Paint)
4393     * @see #LAYER_TYPE_SOFTWARE
4394     * @see #LAYER_TYPE_HARDWARE
4395     */
4396    public static final int LAYER_TYPE_NONE = 0;
4397
4398    /**
4399     * <p>Indicates that the view has a software layer. A software layer is backed
4400     * by a bitmap and causes the view to be rendered using Android's software
4401     * rendering pipeline, even if hardware acceleration is enabled.</p>
4402     *
4403     * <p>Software layers have various usages:</p>
4404     * <p>When the application is not using hardware acceleration, a software layer
4405     * is useful to apply a specific color filter and/or blending mode and/or
4406     * translucency to a view and all its children.</p>
4407     * <p>When the application is using hardware acceleration, a software layer
4408     * is useful to render drawing primitives not supported by the hardware
4409     * accelerated pipeline. It can also be used to cache a complex view tree
4410     * into a texture and reduce the complexity of drawing operations. For instance,
4411     * when animating a complex view tree with a translation, a software layer can
4412     * be used to render the view tree only once.</p>
4413     * <p>Software layers should be avoided when the affected view tree updates
4414     * often. Every update will require to re-render the software layer, which can
4415     * potentially be slow (particularly when hardware acceleration is turned on
4416     * since the layer will have to be uploaded into a hardware texture after every
4417     * update.)</p>
4418     *
4419     * @see #getLayerType()
4420     * @see #setLayerType(int, android.graphics.Paint)
4421     * @see #LAYER_TYPE_NONE
4422     * @see #LAYER_TYPE_HARDWARE
4423     */
4424    public static final int LAYER_TYPE_SOFTWARE = 1;
4425
4426    /**
4427     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4428     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4429     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4430     * rendering pipeline, but only if hardware acceleration is turned on for the
4431     * view hierarchy. When hardware acceleration is turned off, hardware layers
4432     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4433     *
4434     * <p>A hardware layer is useful to apply a specific color filter and/or
4435     * blending mode and/or translucency to a view and all its children.</p>
4436     * <p>A hardware layer can be used to cache a complex view tree into a
4437     * texture and reduce the complexity of drawing operations. For instance,
4438     * when animating a complex view tree with a translation, a hardware layer can
4439     * be used to render the view tree only once.</p>
4440     * <p>A hardware layer can also be used to increase the rendering quality when
4441     * rotation transformations are applied on a view. It can also be used to
4442     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4443     *
4444     * @see #getLayerType()
4445     * @see #setLayerType(int, android.graphics.Paint)
4446     * @see #LAYER_TYPE_NONE
4447     * @see #LAYER_TYPE_SOFTWARE
4448     */
4449    public static final int LAYER_TYPE_HARDWARE = 2;
4450
4451    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4452            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4453            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4454            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4455    })
4456    int mLayerType = LAYER_TYPE_NONE;
4457    Paint mLayerPaint;
4458
4459    /**
4460     * Set to true when drawing cache is enabled and cannot be created.
4461     *
4462     * @hide
4463     */
4464    public boolean mCachingFailed;
4465    private Bitmap mDrawingCache;
4466    private Bitmap mUnscaledDrawingCache;
4467
4468    /**
4469     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4470     * <p>
4471     * When non-null and valid, this is expected to contain an up-to-date copy
4472     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4473     * cleanup.
4474     */
4475    final RenderNode mRenderNode;
4476
4477    /**
4478     * Set to true when the view is sending hover accessibility events because it
4479     * is the innermost hovered view.
4480     */
4481    private boolean mSendingHoverAccessibilityEvents;
4482
4483    /**
4484     * Delegate for injecting accessibility functionality.
4485     */
4486    AccessibilityDelegate mAccessibilityDelegate;
4487
4488    /**
4489     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4490     * and add/remove objects to/from the overlay directly through the Overlay methods.
4491     */
4492    ViewOverlay mOverlay;
4493
4494    /**
4495     * The currently active parent view for receiving delegated nested scrolling events.
4496     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4497     * by {@link #stopNestedScroll()} at the same point where we clear
4498     * requestDisallowInterceptTouchEvent.
4499     */
4500    private ViewParent mNestedScrollingParent;
4501
4502    /**
4503     * Consistency verifier for debugging purposes.
4504     * @hide
4505     */
4506    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4507            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4508                    new InputEventConsistencyVerifier(this, 0) : null;
4509
4510    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4511
4512    private int[] mTempNestedScrollConsumed;
4513
4514    /**
4515     * An overlay is going to draw this View instead of being drawn as part of this
4516     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4517     * when this view is invalidated.
4518     */
4519    GhostView mGhostView;
4520
4521    /**
4522     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4523     * @hide
4524     */
4525    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4526    public String[] mAttributes;
4527
4528    /**
4529     * Maps a Resource id to its name.
4530     */
4531    private static SparseArray<String> mAttributeMap;
4532
4533    /**
4534     * Queue of pending runnables. Used to postpone calls to post() until this
4535     * view is attached and has a handler.
4536     */
4537    private HandlerActionQueue mRunQueue;
4538
4539    /**
4540     * The pointer icon when the mouse hovers on this view. The default is null.
4541     */
4542    private PointerIcon mPointerIcon;
4543
4544    /**
4545     * @hide
4546     */
4547    String mStartActivityRequestWho;
4548
4549    @Nullable
4550    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4551
4552    /** Used to delay visibility updates sent to the autofill manager */
4553    private Handler mVisibilityChangeForAutofillHandler;
4554
4555    /**
4556     * Simple constructor to use when creating a view from code.
4557     *
4558     * @param context The Context the view is running in, through which it can
4559     *        access the current theme, resources, etc.
4560     */
4561    public View(Context context) {
4562        mContext = context;
4563        mResources = context != null ? context.getResources() : null;
4564        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4565        // Set some flags defaults
4566        mPrivateFlags2 =
4567                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4568                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4569                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4570                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4571                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4572                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4573        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4574        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4575        mUserPaddingStart = UNDEFINED_PADDING;
4576        mUserPaddingEnd = UNDEFINED_PADDING;
4577        mRenderNode = RenderNode.create(getClass().getName(), this);
4578
4579        if (!sCompatibilityDone && context != null) {
4580            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4581
4582            // Older apps may need this compatibility hack for measurement.
4583            sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4584
4585            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4586            // of whether a layout was requested on that View.
4587            sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4588
4589            Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4590            Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
4591
4592            // In M and newer, our widgets can pass a "hint" value in the size
4593            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4594            // know what the expected parent size is going to be, so e.g. list items can size
4595            // themselves at 1/3 the size of their container. It breaks older apps though,
4596            // specifically apps that use some popular open source libraries.
4597            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4598
4599            // Old versions of the platform would give different results from
4600            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4601            // modes, so we always need to run an additional EXACTLY pass.
4602            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4603
4604            // Prior to N, layout params could change without requiring a
4605            // subsequent call to setLayoutParams() and they would usually
4606            // work. Partial layout breaks this assumption.
4607            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4608
4609            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4610            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4611            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4612
4613            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4614            // in apps so we target check it to avoid breaking existing apps.
4615            sPreserveMarginParamsInLayoutParamConversion =
4616                    targetSdkVersion >= Build.VERSION_CODES.N;
4617
4618            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4619
4620            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4621
4622            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4623
4624            sUseDefaultFocusHighlight = context.getResources().getBoolean(
4625                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
4626
4627            sCompatibilityDone = true;
4628        }
4629    }
4630
4631    /**
4632     * Constructor that is called when inflating a view from XML. This is called
4633     * when a view is being constructed from an XML file, supplying attributes
4634     * that were specified in the XML file. This version uses a default style of
4635     * 0, so the only attribute values applied are those in the Context's Theme
4636     * and the given AttributeSet.
4637     *
4638     * <p>
4639     * The method onFinishInflate() will be called after all children have been
4640     * added.
4641     *
4642     * @param context The Context the view is running in, through which it can
4643     *        access the current theme, resources, etc.
4644     * @param attrs The attributes of the XML tag that is inflating the view.
4645     * @see #View(Context, AttributeSet, int)
4646     */
4647    public View(Context context, @Nullable AttributeSet attrs) {
4648        this(context, attrs, 0);
4649    }
4650
4651    /**
4652     * Perform inflation from XML and apply a class-specific base style from a
4653     * theme attribute. This constructor of View allows subclasses to use their
4654     * own base style when they are inflating. For example, a Button class's
4655     * constructor would call this version of the super class constructor and
4656     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4657     * allows the theme's button style to modify all of the base view attributes
4658     * (in particular its background) as well as the Button class's attributes.
4659     *
4660     * @param context The Context the view is running in, through which it can
4661     *        access the current theme, resources, etc.
4662     * @param attrs The attributes of the XML tag that is inflating the view.
4663     * @param defStyleAttr An attribute in the current theme that contains a
4664     *        reference to a style resource that supplies default values for
4665     *        the view. Can be 0 to not look for defaults.
4666     * @see #View(Context, AttributeSet)
4667     */
4668    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4669        this(context, attrs, defStyleAttr, 0);
4670    }
4671
4672    /**
4673     * Perform inflation from XML and apply a class-specific base style from a
4674     * theme attribute or style resource. This constructor of View allows
4675     * subclasses to use their own base style when they are inflating.
4676     * <p>
4677     * When determining the final value of a particular attribute, there are
4678     * four inputs that come into play:
4679     * <ol>
4680     * <li>Any attribute values in the given AttributeSet.
4681     * <li>The style resource specified in the AttributeSet (named "style").
4682     * <li>The default style specified by <var>defStyleAttr</var>.
4683     * <li>The default style specified by <var>defStyleRes</var>.
4684     * <li>The base values in this theme.
4685     * </ol>
4686     * <p>
4687     * Each of these inputs is considered in-order, with the first listed taking
4688     * precedence over the following ones. In other words, if in the
4689     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4690     * , then the button's text will <em>always</em> be black, regardless of
4691     * what is specified in any of the styles.
4692     *
4693     * @param context The Context the view is running in, through which it can
4694     *        access the current theme, resources, etc.
4695     * @param attrs The attributes of the XML tag that is inflating the view.
4696     * @param defStyleAttr An attribute in the current theme that contains a
4697     *        reference to a style resource that supplies default values for
4698     *        the view. Can be 0 to not look for defaults.
4699     * @param defStyleRes A resource identifier of a style resource that
4700     *        supplies default values for the view, used only if
4701     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4702     *        to not look for defaults.
4703     * @see #View(Context, AttributeSet, int)
4704     */
4705    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4706        this(context);
4707
4708        final TypedArray a = context.obtainStyledAttributes(
4709                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4710
4711        if (mDebugViewAttributes) {
4712            saveAttributeData(attrs, a);
4713        }
4714
4715        Drawable background = null;
4716
4717        int leftPadding = -1;
4718        int topPadding = -1;
4719        int rightPadding = -1;
4720        int bottomPadding = -1;
4721        int startPadding = UNDEFINED_PADDING;
4722        int endPadding = UNDEFINED_PADDING;
4723
4724        int padding = -1;
4725        int paddingHorizontal = -1;
4726        int paddingVertical = -1;
4727
4728        int viewFlagValues = 0;
4729        int viewFlagMasks = 0;
4730
4731        boolean setScrollContainer = false;
4732
4733        int x = 0;
4734        int y = 0;
4735
4736        float tx = 0;
4737        float ty = 0;
4738        float tz = 0;
4739        float elevation = 0;
4740        float rotation = 0;
4741        float rotationX = 0;
4742        float rotationY = 0;
4743        float sx = 1f;
4744        float sy = 1f;
4745        boolean transformSet = false;
4746
4747        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4748        int overScrollMode = mOverScrollMode;
4749        boolean initializeScrollbars = false;
4750        boolean initializeScrollIndicators = false;
4751
4752        boolean startPaddingDefined = false;
4753        boolean endPaddingDefined = false;
4754        boolean leftPaddingDefined = false;
4755        boolean rightPaddingDefined = false;
4756
4757        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4758
4759        // Set default values.
4760        viewFlagValues |= FOCUSABLE_AUTO;
4761        viewFlagMasks |= FOCUSABLE_AUTO;
4762
4763        final int N = a.getIndexCount();
4764        for (int i = 0; i < N; i++) {
4765            int attr = a.getIndex(i);
4766            switch (attr) {
4767                case com.android.internal.R.styleable.View_background:
4768                    background = a.getDrawable(attr);
4769                    break;
4770                case com.android.internal.R.styleable.View_padding:
4771                    padding = a.getDimensionPixelSize(attr, -1);
4772                    mUserPaddingLeftInitial = padding;
4773                    mUserPaddingRightInitial = padding;
4774                    leftPaddingDefined = true;
4775                    rightPaddingDefined = true;
4776                    break;
4777                case com.android.internal.R.styleable.View_paddingHorizontal:
4778                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4779                    mUserPaddingLeftInitial = paddingHorizontal;
4780                    mUserPaddingRightInitial = paddingHorizontal;
4781                    leftPaddingDefined = true;
4782                    rightPaddingDefined = true;
4783                    break;
4784                case com.android.internal.R.styleable.View_paddingVertical:
4785                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4786                    break;
4787                 case com.android.internal.R.styleable.View_paddingLeft:
4788                    leftPadding = a.getDimensionPixelSize(attr, -1);
4789                    mUserPaddingLeftInitial = leftPadding;
4790                    leftPaddingDefined = true;
4791                    break;
4792                case com.android.internal.R.styleable.View_paddingTop:
4793                    topPadding = a.getDimensionPixelSize(attr, -1);
4794                    break;
4795                case com.android.internal.R.styleable.View_paddingRight:
4796                    rightPadding = a.getDimensionPixelSize(attr, -1);
4797                    mUserPaddingRightInitial = rightPadding;
4798                    rightPaddingDefined = true;
4799                    break;
4800                case com.android.internal.R.styleable.View_paddingBottom:
4801                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4802                    break;
4803                case com.android.internal.R.styleable.View_paddingStart:
4804                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4805                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4806                    break;
4807                case com.android.internal.R.styleable.View_paddingEnd:
4808                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4809                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4810                    break;
4811                case com.android.internal.R.styleable.View_scrollX:
4812                    x = a.getDimensionPixelOffset(attr, 0);
4813                    break;
4814                case com.android.internal.R.styleable.View_scrollY:
4815                    y = a.getDimensionPixelOffset(attr, 0);
4816                    break;
4817                case com.android.internal.R.styleable.View_alpha:
4818                    setAlpha(a.getFloat(attr, 1f));
4819                    break;
4820                case com.android.internal.R.styleable.View_transformPivotX:
4821                    setPivotX(a.getDimension(attr, 0));
4822                    break;
4823                case com.android.internal.R.styleable.View_transformPivotY:
4824                    setPivotY(a.getDimension(attr, 0));
4825                    break;
4826                case com.android.internal.R.styleable.View_translationX:
4827                    tx = a.getDimension(attr, 0);
4828                    transformSet = true;
4829                    break;
4830                case com.android.internal.R.styleable.View_translationY:
4831                    ty = a.getDimension(attr, 0);
4832                    transformSet = true;
4833                    break;
4834                case com.android.internal.R.styleable.View_translationZ:
4835                    tz = a.getDimension(attr, 0);
4836                    transformSet = true;
4837                    break;
4838                case com.android.internal.R.styleable.View_elevation:
4839                    elevation = a.getDimension(attr, 0);
4840                    transformSet = true;
4841                    break;
4842                case com.android.internal.R.styleable.View_rotation:
4843                    rotation = a.getFloat(attr, 0);
4844                    transformSet = true;
4845                    break;
4846                case com.android.internal.R.styleable.View_rotationX:
4847                    rotationX = a.getFloat(attr, 0);
4848                    transformSet = true;
4849                    break;
4850                case com.android.internal.R.styleable.View_rotationY:
4851                    rotationY = a.getFloat(attr, 0);
4852                    transformSet = true;
4853                    break;
4854                case com.android.internal.R.styleable.View_scaleX:
4855                    sx = a.getFloat(attr, 1f);
4856                    transformSet = true;
4857                    break;
4858                case com.android.internal.R.styleable.View_scaleY:
4859                    sy = a.getFloat(attr, 1f);
4860                    transformSet = true;
4861                    break;
4862                case com.android.internal.R.styleable.View_id:
4863                    mID = a.getResourceId(attr, NO_ID);
4864                    break;
4865                case com.android.internal.R.styleable.View_tag:
4866                    mTag = a.getText(attr);
4867                    break;
4868                case com.android.internal.R.styleable.View_fitsSystemWindows:
4869                    if (a.getBoolean(attr, false)) {
4870                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4871                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4872                    }
4873                    break;
4874                case com.android.internal.R.styleable.View_focusable:
4875                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4876                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4877                        viewFlagMasks |= FOCUSABLE_MASK;
4878                    }
4879                    break;
4880                case com.android.internal.R.styleable.View_focusableInTouchMode:
4881                    if (a.getBoolean(attr, false)) {
4882                        // unset auto focus since focusableInTouchMode implies explicit focusable
4883                        viewFlagValues &= ~FOCUSABLE_AUTO;
4884                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4885                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4886                    }
4887                    break;
4888                case com.android.internal.R.styleable.View_clickable:
4889                    if (a.getBoolean(attr, false)) {
4890                        viewFlagValues |= CLICKABLE;
4891                        viewFlagMasks |= CLICKABLE;
4892                    }
4893                    break;
4894                case com.android.internal.R.styleable.View_longClickable:
4895                    if (a.getBoolean(attr, false)) {
4896                        viewFlagValues |= LONG_CLICKABLE;
4897                        viewFlagMasks |= LONG_CLICKABLE;
4898                    }
4899                    break;
4900                case com.android.internal.R.styleable.View_contextClickable:
4901                    if (a.getBoolean(attr, false)) {
4902                        viewFlagValues |= CONTEXT_CLICKABLE;
4903                        viewFlagMasks |= CONTEXT_CLICKABLE;
4904                    }
4905                    break;
4906                case com.android.internal.R.styleable.View_saveEnabled:
4907                    if (!a.getBoolean(attr, true)) {
4908                        viewFlagValues |= SAVE_DISABLED;
4909                        viewFlagMasks |= SAVE_DISABLED_MASK;
4910                    }
4911                    break;
4912                case com.android.internal.R.styleable.View_duplicateParentState:
4913                    if (a.getBoolean(attr, false)) {
4914                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4915                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4916                    }
4917                    break;
4918                case com.android.internal.R.styleable.View_visibility:
4919                    final int visibility = a.getInt(attr, 0);
4920                    if (visibility != 0) {
4921                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4922                        viewFlagMasks |= VISIBILITY_MASK;
4923                    }
4924                    break;
4925                case com.android.internal.R.styleable.View_layoutDirection:
4926                    // Clear any layout direction flags (included resolved bits) already set
4927                    mPrivateFlags2 &=
4928                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4929                    // Set the layout direction flags depending on the value of the attribute
4930                    final int layoutDirection = a.getInt(attr, -1);
4931                    final int value = (layoutDirection != -1) ?
4932                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4933                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4934                    break;
4935                case com.android.internal.R.styleable.View_drawingCacheQuality:
4936                    final int cacheQuality = a.getInt(attr, 0);
4937                    if (cacheQuality != 0) {
4938                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4939                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4940                    }
4941                    break;
4942                case com.android.internal.R.styleable.View_contentDescription:
4943                    setContentDescription(a.getString(attr));
4944                    break;
4945                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4946                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4947                    break;
4948                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4949                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4950                    break;
4951                case com.android.internal.R.styleable.View_labelFor:
4952                    setLabelFor(a.getResourceId(attr, NO_ID));
4953                    break;
4954                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4955                    if (!a.getBoolean(attr, true)) {
4956                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4957                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4958                    }
4959                    break;
4960                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4961                    if (!a.getBoolean(attr, true)) {
4962                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4963                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4964                    }
4965                    break;
4966                case R.styleable.View_scrollbars:
4967                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4968                    if (scrollbars != SCROLLBARS_NONE) {
4969                        viewFlagValues |= scrollbars;
4970                        viewFlagMasks |= SCROLLBARS_MASK;
4971                        initializeScrollbars = true;
4972                    }
4973                    break;
4974                //noinspection deprecation
4975                case R.styleable.View_fadingEdge:
4976                    if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4977                        // Ignore the attribute starting with ICS
4978                        break;
4979                    }
4980                    // With builds < ICS, fall through and apply fading edges
4981                case R.styleable.View_requiresFadingEdge:
4982                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4983                    if (fadingEdge != FADING_EDGE_NONE) {
4984                        viewFlagValues |= fadingEdge;
4985                        viewFlagMasks |= FADING_EDGE_MASK;
4986                        initializeFadingEdgeInternal(a);
4987                    }
4988                    break;
4989                case R.styleable.View_scrollbarStyle:
4990                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4991                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4992                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4993                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4994                    }
4995                    break;
4996                case R.styleable.View_isScrollContainer:
4997                    setScrollContainer = true;
4998                    if (a.getBoolean(attr, false)) {
4999                        setScrollContainer(true);
5000                    }
5001                    break;
5002                case com.android.internal.R.styleable.View_keepScreenOn:
5003                    if (a.getBoolean(attr, false)) {
5004                        viewFlagValues |= KEEP_SCREEN_ON;
5005                        viewFlagMasks |= KEEP_SCREEN_ON;
5006                    }
5007                    break;
5008                case R.styleable.View_filterTouchesWhenObscured:
5009                    if (a.getBoolean(attr, false)) {
5010                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
5011                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
5012                    }
5013                    break;
5014                case R.styleable.View_nextFocusLeft:
5015                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
5016                    break;
5017                case R.styleable.View_nextFocusRight:
5018                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
5019                    break;
5020                case R.styleable.View_nextFocusUp:
5021                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
5022                    break;
5023                case R.styleable.View_nextFocusDown:
5024                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
5025                    break;
5026                case R.styleable.View_nextFocusForward:
5027                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
5028                    break;
5029                case R.styleable.View_nextClusterForward:
5030                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
5031                    break;
5032                case R.styleable.View_minWidth:
5033                    mMinWidth = a.getDimensionPixelSize(attr, 0);
5034                    break;
5035                case R.styleable.View_minHeight:
5036                    mMinHeight = a.getDimensionPixelSize(attr, 0);
5037                    break;
5038                case R.styleable.View_onClick:
5039                    if (context.isRestricted()) {
5040                        throw new IllegalStateException("The android:onClick attribute cannot "
5041                                + "be used within a restricted context");
5042                    }
5043
5044                    final String handlerName = a.getString(attr);
5045                    if (handlerName != null) {
5046                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5047                    }
5048                    break;
5049                case R.styleable.View_overScrollMode:
5050                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5051                    break;
5052                case R.styleable.View_verticalScrollbarPosition:
5053                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5054                    break;
5055                case R.styleable.View_layerType:
5056                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5057                    break;
5058                case R.styleable.View_textDirection:
5059                    // Clear any text direction flag already set
5060                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5061                    // Set the text direction flags depending on the value of the attribute
5062                    final int textDirection = a.getInt(attr, -1);
5063                    if (textDirection != -1) {
5064                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5065                    }
5066                    break;
5067                case R.styleable.View_textAlignment:
5068                    // Clear any text alignment flag already set
5069                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5070                    // Set the text alignment flag depending on the value of the attribute
5071                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5072                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5073                    break;
5074                case R.styleable.View_importantForAccessibility:
5075                    setImportantForAccessibility(a.getInt(attr,
5076                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5077                    break;
5078                case R.styleable.View_accessibilityLiveRegion:
5079                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5080                    break;
5081                case R.styleable.View_transitionName:
5082                    setTransitionName(a.getString(attr));
5083                    break;
5084                case R.styleable.View_nestedScrollingEnabled:
5085                    setNestedScrollingEnabled(a.getBoolean(attr, false));
5086                    break;
5087                case R.styleable.View_stateListAnimator:
5088                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5089                            a.getResourceId(attr, 0)));
5090                    break;
5091                case R.styleable.View_backgroundTint:
5092                    // This will get applied later during setBackground().
5093                    if (mBackgroundTint == null) {
5094                        mBackgroundTint = new TintInfo();
5095                    }
5096                    mBackgroundTint.mTintList = a.getColorStateList(
5097                            R.styleable.View_backgroundTint);
5098                    mBackgroundTint.mHasTintList = true;
5099                    break;
5100                case R.styleable.View_backgroundTintMode:
5101                    // This will get applied later during setBackground().
5102                    if (mBackgroundTint == null) {
5103                        mBackgroundTint = new TintInfo();
5104                    }
5105                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
5106                            R.styleable.View_backgroundTintMode, -1), null);
5107                    mBackgroundTint.mHasTintMode = true;
5108                    break;
5109                case R.styleable.View_outlineProvider:
5110                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5111                            PROVIDER_BACKGROUND));
5112                    break;
5113                case R.styleable.View_foreground:
5114                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5115                        setForeground(a.getDrawable(attr));
5116                    }
5117                    break;
5118                case R.styleable.View_foregroundGravity:
5119                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5120                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5121                    }
5122                    break;
5123                case R.styleable.View_foregroundTintMode:
5124                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5125                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
5126                    }
5127                    break;
5128                case R.styleable.View_foregroundTint:
5129                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5130                        setForegroundTintList(a.getColorStateList(attr));
5131                    }
5132                    break;
5133                case R.styleable.View_foregroundInsidePadding:
5134                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5135                        if (mForegroundInfo == null) {
5136                            mForegroundInfo = new ForegroundInfo();
5137                        }
5138                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5139                                mForegroundInfo.mInsidePadding);
5140                    }
5141                    break;
5142                case R.styleable.View_scrollIndicators:
5143                    final int scrollIndicators =
5144                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5145                                    & SCROLL_INDICATORS_PFLAG3_MASK;
5146                    if (scrollIndicators != 0) {
5147                        mPrivateFlags3 |= scrollIndicators;
5148                        initializeScrollIndicators = true;
5149                    }
5150                    break;
5151                case R.styleable.View_pointerIcon:
5152                    final int resourceId = a.getResourceId(attr, 0);
5153                    if (resourceId != 0) {
5154                        setPointerIcon(PointerIcon.load(
5155                                context.getResources(), resourceId));
5156                    } else {
5157                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5158                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5159                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5160                        }
5161                    }
5162                    break;
5163                case R.styleable.View_forceHasOverlappingRendering:
5164                    if (a.peekValue(attr) != null) {
5165                        forceHasOverlappingRendering(a.getBoolean(attr, true));
5166                    }
5167                    break;
5168                case R.styleable.View_tooltipText:
5169                    setTooltipText(a.getText(attr));
5170                    break;
5171                case R.styleable.View_keyboardNavigationCluster:
5172                    if (a.peekValue(attr) != null) {
5173                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
5174                    }
5175                    break;
5176                case R.styleable.View_focusedByDefault:
5177                    if (a.peekValue(attr) != null) {
5178                        setFocusedByDefault(a.getBoolean(attr, true));
5179                    }
5180                    break;
5181                case R.styleable.View_autofillHints:
5182                    if (a.peekValue(attr) != null) {
5183                        CharSequence[] rawHints = null;
5184                        String rawString = null;
5185
5186                        if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5187                            int resId = a.getResourceId(attr, 0);
5188
5189                            try {
5190                                rawHints = a.getTextArray(attr);
5191                            } catch (Resources.NotFoundException e) {
5192                                rawString = getResources().getString(resId);
5193                            }
5194                        } else {
5195                            rawString = a.getString(attr);
5196                        }
5197
5198                        if (rawHints == null) {
5199                            if (rawString == null) {
5200                                throw new IllegalArgumentException(
5201                                        "Could not resolve autofillHints");
5202                            } else {
5203                                rawHints = rawString.split(",");
5204                            }
5205                        }
5206
5207                        String[] hints = new String[rawHints.length];
5208
5209                        int numHints = rawHints.length;
5210                        for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5211                            hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5212                        }
5213                        setAutofillHints(hints);
5214                    }
5215                    break;
5216                case R.styleable.View_importantForAutofill:
5217                    if (a.peekValue(attr) != null) {
5218                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5219                    }
5220                    break;
5221                case R.styleable.View_defaultFocusHighlightEnabled:
5222                    if (a.peekValue(attr) != null) {
5223                        setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5224                    }
5225                    break;
5226            }
5227        }
5228
5229        setOverScrollMode(overScrollMode);
5230
5231        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5232        // the resolved layout direction). Those cached values will be used later during padding
5233        // resolution.
5234        mUserPaddingStart = startPadding;
5235        mUserPaddingEnd = endPadding;
5236
5237        if (background != null) {
5238            setBackground(background);
5239        }
5240
5241        // setBackground above will record that padding is currently provided by the background.
5242        // If we have padding specified via xml, record that here instead and use it.
5243        mLeftPaddingDefined = leftPaddingDefined;
5244        mRightPaddingDefined = rightPaddingDefined;
5245
5246        if (padding >= 0) {
5247            leftPadding = padding;
5248            topPadding = padding;
5249            rightPadding = padding;
5250            bottomPadding = padding;
5251            mUserPaddingLeftInitial = padding;
5252            mUserPaddingRightInitial = padding;
5253        } else {
5254            if (paddingHorizontal >= 0) {
5255                leftPadding = paddingHorizontal;
5256                rightPadding = paddingHorizontal;
5257                mUserPaddingLeftInitial = paddingHorizontal;
5258                mUserPaddingRightInitial = paddingHorizontal;
5259            }
5260            if (paddingVertical >= 0) {
5261                topPadding = paddingVertical;
5262                bottomPadding = paddingVertical;
5263            }
5264        }
5265
5266        if (isRtlCompatibilityMode()) {
5267            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5268            // left / right padding are used if defined (meaning here nothing to do). If they are not
5269            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5270            // start / end and resolve them as left / right (layout direction is not taken into account).
5271            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5272            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5273            // defined.
5274            if (!mLeftPaddingDefined && startPaddingDefined) {
5275                leftPadding = startPadding;
5276            }
5277            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5278            if (!mRightPaddingDefined && endPaddingDefined) {
5279                rightPadding = endPadding;
5280            }
5281            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5282        } else {
5283            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5284            // values defined. Otherwise, left /right values are used.
5285            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5286            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5287            // defined.
5288            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5289
5290            if (mLeftPaddingDefined && !hasRelativePadding) {
5291                mUserPaddingLeftInitial = leftPadding;
5292            }
5293            if (mRightPaddingDefined && !hasRelativePadding) {
5294                mUserPaddingRightInitial = rightPadding;
5295            }
5296        }
5297
5298        internalSetPadding(
5299                mUserPaddingLeftInitial,
5300                topPadding >= 0 ? topPadding : mPaddingTop,
5301                mUserPaddingRightInitial,
5302                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5303
5304        if (viewFlagMasks != 0) {
5305            setFlags(viewFlagValues, viewFlagMasks);
5306        }
5307
5308        if (initializeScrollbars) {
5309            initializeScrollbarsInternal(a);
5310        }
5311
5312        if (initializeScrollIndicators) {
5313            initializeScrollIndicatorsInternal();
5314        }
5315
5316        a.recycle();
5317
5318        // Needs to be called after mViewFlags is set
5319        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5320            recomputePadding();
5321        }
5322
5323        if (x != 0 || y != 0) {
5324            scrollTo(x, y);
5325        }
5326
5327        if (transformSet) {
5328            setTranslationX(tx);
5329            setTranslationY(ty);
5330            setTranslationZ(tz);
5331            setElevation(elevation);
5332            setRotation(rotation);
5333            setRotationX(rotationX);
5334            setRotationY(rotationY);
5335            setScaleX(sx);
5336            setScaleY(sy);
5337        }
5338
5339        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5340            setScrollContainer(true);
5341        }
5342
5343        computeOpaqueFlags();
5344    }
5345
5346    /**
5347     * An implementation of OnClickListener that attempts to lazily load a
5348     * named click handling method from a parent or ancestor context.
5349     */
5350    private static class DeclaredOnClickListener implements OnClickListener {
5351        private final View mHostView;
5352        private final String mMethodName;
5353
5354        private Method mResolvedMethod;
5355        private Context mResolvedContext;
5356
5357        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5358            mHostView = hostView;
5359            mMethodName = methodName;
5360        }
5361
5362        @Override
5363        public void onClick(@NonNull View v) {
5364            if (mResolvedMethod == null) {
5365                resolveMethod(mHostView.getContext(), mMethodName);
5366            }
5367
5368            try {
5369                mResolvedMethod.invoke(mResolvedContext, v);
5370            } catch (IllegalAccessException e) {
5371                throw new IllegalStateException(
5372                        "Could not execute non-public method for android:onClick", e);
5373            } catch (InvocationTargetException e) {
5374                throw new IllegalStateException(
5375                        "Could not execute method for android:onClick", e);
5376            }
5377        }
5378
5379        @NonNull
5380        private void resolveMethod(@Nullable Context context, @NonNull String name) {
5381            while (context != null) {
5382                try {
5383                    if (!context.isRestricted()) {
5384                        final Method method = context.getClass().getMethod(mMethodName, View.class);
5385                        if (method != null) {
5386                            mResolvedMethod = method;
5387                            mResolvedContext = context;
5388                            return;
5389                        }
5390                    }
5391                } catch (NoSuchMethodException e) {
5392                    // Failed to find method, keep searching up the hierarchy.
5393                }
5394
5395                if (context instanceof ContextWrapper) {
5396                    context = ((ContextWrapper) context).getBaseContext();
5397                } else {
5398                    // Can't search up the hierarchy, null out and fail.
5399                    context = null;
5400                }
5401            }
5402
5403            final int id = mHostView.getId();
5404            final String idText = id == NO_ID ? "" : " with id '"
5405                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5406            throw new IllegalStateException("Could not find method " + mMethodName
5407                    + "(View) in a parent or ancestor Context for android:onClick "
5408                    + "attribute defined on view " + mHostView.getClass() + idText);
5409        }
5410    }
5411
5412    /**
5413     * Non-public constructor for use in testing
5414     */
5415    View() {
5416        mResources = null;
5417        mRenderNode = RenderNode.create(getClass().getName(), this);
5418    }
5419
5420    final boolean debugDraw() {
5421        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5422    }
5423
5424    private static SparseArray<String> getAttributeMap() {
5425        if (mAttributeMap == null) {
5426            mAttributeMap = new SparseArray<>();
5427        }
5428        return mAttributeMap;
5429    }
5430
5431    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5432        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5433        final int indexCount = t.getIndexCount();
5434        final String[] attributes = new String[(attrsCount + indexCount) * 2];
5435
5436        int i = 0;
5437
5438        // Store raw XML attributes.
5439        for (int j = 0; j < attrsCount; ++j) {
5440            attributes[i] = attrs.getAttributeName(j);
5441            attributes[i + 1] = attrs.getAttributeValue(j);
5442            i += 2;
5443        }
5444
5445        // Store resolved styleable attributes.
5446        final Resources res = t.getResources();
5447        final SparseArray<String> attributeMap = getAttributeMap();
5448        for (int j = 0; j < indexCount; ++j) {
5449            final int index = t.getIndex(j);
5450            if (!t.hasValueOrEmpty(index)) {
5451                // Value is undefined. Skip it.
5452                continue;
5453            }
5454
5455            final int resourceId = t.getResourceId(index, 0);
5456            if (resourceId == 0) {
5457                // Value is not a reference. Skip it.
5458                continue;
5459            }
5460
5461            String resourceName = attributeMap.get(resourceId);
5462            if (resourceName == null) {
5463                try {
5464                    resourceName = res.getResourceName(resourceId);
5465                } catch (Resources.NotFoundException e) {
5466                    resourceName = "0x" + Integer.toHexString(resourceId);
5467                }
5468                attributeMap.put(resourceId, resourceName);
5469            }
5470
5471            attributes[i] = resourceName;
5472            attributes[i + 1] = t.getString(index);
5473            i += 2;
5474        }
5475
5476        // Trim to fit contents.
5477        final String[] trimmed = new String[i];
5478        System.arraycopy(attributes, 0, trimmed, 0, i);
5479        mAttributes = trimmed;
5480    }
5481
5482    public String toString() {
5483        StringBuilder out = new StringBuilder(128);
5484        out.append(getClass().getName());
5485        out.append('{');
5486        out.append(Integer.toHexString(System.identityHashCode(this)));
5487        out.append(' ');
5488        switch (mViewFlags&VISIBILITY_MASK) {
5489            case VISIBLE: out.append('V'); break;
5490            case INVISIBLE: out.append('I'); break;
5491            case GONE: out.append('G'); break;
5492            default: out.append('.'); break;
5493        }
5494        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5495        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5496        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5497        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5498        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5499        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5500        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5501        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5502        out.append(' ');
5503        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5504        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5505        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5506        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5507            out.append('p');
5508        } else {
5509            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5510        }
5511        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5512        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5513        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5514        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5515        out.append(' ');
5516        out.append(mLeft);
5517        out.append(',');
5518        out.append(mTop);
5519        out.append('-');
5520        out.append(mRight);
5521        out.append(',');
5522        out.append(mBottom);
5523        final int id = getId();
5524        if (id != NO_ID) {
5525            out.append(" #");
5526            out.append(Integer.toHexString(id));
5527            final Resources r = mResources;
5528            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5529                try {
5530                    String pkgname;
5531                    switch (id&0xff000000) {
5532                        case 0x7f000000:
5533                            pkgname="app";
5534                            break;
5535                        case 0x01000000:
5536                            pkgname="android";
5537                            break;
5538                        default:
5539                            pkgname = r.getResourcePackageName(id);
5540                            break;
5541                    }
5542                    String typename = r.getResourceTypeName(id);
5543                    String entryname = r.getResourceEntryName(id);
5544                    out.append(" ");
5545                    out.append(pkgname);
5546                    out.append(":");
5547                    out.append(typename);
5548                    out.append("/");
5549                    out.append(entryname);
5550                } catch (Resources.NotFoundException e) {
5551                }
5552            }
5553        }
5554        out.append("}");
5555        return out.toString();
5556    }
5557
5558    /**
5559     * <p>
5560     * Initializes the fading edges from a given set of styled attributes. This
5561     * method should be called by subclasses that need fading edges and when an
5562     * instance of these subclasses is created programmatically rather than
5563     * being inflated from XML. This method is automatically called when the XML
5564     * is inflated.
5565     * </p>
5566     *
5567     * @param a the styled attributes set to initialize the fading edges from
5568     *
5569     * @removed
5570     */
5571    protected void initializeFadingEdge(TypedArray a) {
5572        // This method probably shouldn't have been included in the SDK to begin with.
5573        // It relies on 'a' having been initialized using an attribute filter array that is
5574        // not publicly available to the SDK. The old method has been renamed
5575        // to initializeFadingEdgeInternal and hidden for framework use only;
5576        // this one initializes using defaults to make it safe to call for apps.
5577
5578        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5579
5580        initializeFadingEdgeInternal(arr);
5581
5582        arr.recycle();
5583    }
5584
5585    /**
5586     * <p>
5587     * Initializes the fading edges from a given set of styled attributes. This
5588     * method should be called by subclasses that need fading edges and when an
5589     * instance of these subclasses is created programmatically rather than
5590     * being inflated from XML. This method is automatically called when the XML
5591     * is inflated.
5592     * </p>
5593     *
5594     * @param a the styled attributes set to initialize the fading edges from
5595     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5596     */
5597    protected void initializeFadingEdgeInternal(TypedArray a) {
5598        initScrollCache();
5599
5600        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5601                R.styleable.View_fadingEdgeLength,
5602                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5603    }
5604
5605    /**
5606     * Returns the size of the vertical faded edges used to indicate that more
5607     * content in this view is visible.
5608     *
5609     * @return The size in pixels of the vertical faded edge or 0 if vertical
5610     *         faded edges are not enabled for this view.
5611     * @attr ref android.R.styleable#View_fadingEdgeLength
5612     */
5613    public int getVerticalFadingEdgeLength() {
5614        if (isVerticalFadingEdgeEnabled()) {
5615            ScrollabilityCache cache = mScrollCache;
5616            if (cache != null) {
5617                return cache.fadingEdgeLength;
5618            }
5619        }
5620        return 0;
5621    }
5622
5623    /**
5624     * Set the size of the faded edge used to indicate that more content in this
5625     * view is available.  Will not change whether the fading edge is enabled; use
5626     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5627     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5628     * for the vertical or horizontal fading edges.
5629     *
5630     * @param length The size in pixels of the faded edge used to indicate that more
5631     *        content in this view is visible.
5632     */
5633    public void setFadingEdgeLength(int length) {
5634        initScrollCache();
5635        mScrollCache.fadingEdgeLength = length;
5636    }
5637
5638    /**
5639     * Returns the size of the horizontal faded edges used to indicate that more
5640     * content in this view is visible.
5641     *
5642     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5643     *         faded edges are not enabled for this view.
5644     * @attr ref android.R.styleable#View_fadingEdgeLength
5645     */
5646    public int getHorizontalFadingEdgeLength() {
5647        if (isHorizontalFadingEdgeEnabled()) {
5648            ScrollabilityCache cache = mScrollCache;
5649            if (cache != null) {
5650                return cache.fadingEdgeLength;
5651            }
5652        }
5653        return 0;
5654    }
5655
5656    /**
5657     * Returns the width of the vertical scrollbar.
5658     *
5659     * @return The width in pixels of the vertical scrollbar or 0 if there
5660     *         is no vertical scrollbar.
5661     */
5662    public int getVerticalScrollbarWidth() {
5663        ScrollabilityCache cache = mScrollCache;
5664        if (cache != null) {
5665            ScrollBarDrawable scrollBar = cache.scrollBar;
5666            if (scrollBar != null) {
5667                int size = scrollBar.getSize(true);
5668                if (size <= 0) {
5669                    size = cache.scrollBarSize;
5670                }
5671                return size;
5672            }
5673            return 0;
5674        }
5675        return 0;
5676    }
5677
5678    /**
5679     * Returns the height of the horizontal scrollbar.
5680     *
5681     * @return The height in pixels of the horizontal scrollbar or 0 if
5682     *         there is no horizontal scrollbar.
5683     */
5684    protected int getHorizontalScrollbarHeight() {
5685        ScrollabilityCache cache = mScrollCache;
5686        if (cache != null) {
5687            ScrollBarDrawable scrollBar = cache.scrollBar;
5688            if (scrollBar != null) {
5689                int size = scrollBar.getSize(false);
5690                if (size <= 0) {
5691                    size = cache.scrollBarSize;
5692                }
5693                return size;
5694            }
5695            return 0;
5696        }
5697        return 0;
5698    }
5699
5700    /**
5701     * <p>
5702     * Initializes the scrollbars from a given set of styled attributes. This
5703     * method should be called by subclasses that need scrollbars and when an
5704     * instance of these subclasses is created programmatically rather than
5705     * being inflated from XML. This method is automatically called when the XML
5706     * is inflated.
5707     * </p>
5708     *
5709     * @param a the styled attributes set to initialize the scrollbars from
5710     *
5711     * @removed
5712     */
5713    protected void initializeScrollbars(TypedArray a) {
5714        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5715        // using the View filter array which is not available to the SDK. As such, internal
5716        // framework usage now uses initializeScrollbarsInternal and we grab a default
5717        // TypedArray with the right filter instead here.
5718        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5719
5720        initializeScrollbarsInternal(arr);
5721
5722        // We ignored the method parameter. Recycle the one we actually did use.
5723        arr.recycle();
5724    }
5725
5726    /**
5727     * <p>
5728     * Initializes the scrollbars from a given set of styled attributes. This
5729     * method should be called by subclasses that need scrollbars and when an
5730     * instance of these subclasses is created programmatically rather than
5731     * being inflated from XML. This method is automatically called when the XML
5732     * is inflated.
5733     * </p>
5734     *
5735     * @param a the styled attributes set to initialize the scrollbars from
5736     * @hide
5737     */
5738    protected void initializeScrollbarsInternal(TypedArray a) {
5739        initScrollCache();
5740
5741        final ScrollabilityCache scrollabilityCache = mScrollCache;
5742
5743        if (scrollabilityCache.scrollBar == null) {
5744            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5745            scrollabilityCache.scrollBar.setState(getDrawableState());
5746            scrollabilityCache.scrollBar.setCallback(this);
5747        }
5748
5749        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5750
5751        if (!fadeScrollbars) {
5752            scrollabilityCache.state = ScrollabilityCache.ON;
5753        }
5754        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5755
5756
5757        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5758                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5759                        .getScrollBarFadeDuration());
5760        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5761                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5762                ViewConfiguration.getScrollDefaultDelay());
5763
5764
5765        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5766                com.android.internal.R.styleable.View_scrollbarSize,
5767                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5768
5769        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5770        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5771
5772        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5773        if (thumb != null) {
5774            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5775        }
5776
5777        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5778                false);
5779        if (alwaysDraw) {
5780            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5781        }
5782
5783        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5784        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5785
5786        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5787        if (thumb != null) {
5788            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5789        }
5790
5791        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5792                false);
5793        if (alwaysDraw) {
5794            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5795        }
5796
5797        // Apply layout direction to the new Drawables if needed
5798        final int layoutDirection = getLayoutDirection();
5799        if (track != null) {
5800            track.setLayoutDirection(layoutDirection);
5801        }
5802        if (thumb != null) {
5803            thumb.setLayoutDirection(layoutDirection);
5804        }
5805
5806        // Re-apply user/background padding so that scrollbar(s) get added
5807        resolvePadding();
5808    }
5809
5810    private void initializeScrollIndicatorsInternal() {
5811        // Some day maybe we'll break this into top/left/start/etc. and let the
5812        // client control it. Until then, you can have any scroll indicator you
5813        // want as long as it's a 1dp foreground-colored rectangle.
5814        if (mScrollIndicatorDrawable == null) {
5815            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5816        }
5817    }
5818
5819    /**
5820     * <p>
5821     * Initalizes the scrollability cache if necessary.
5822     * </p>
5823     */
5824    private void initScrollCache() {
5825        if (mScrollCache == null) {
5826            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5827        }
5828    }
5829
5830    private ScrollabilityCache getScrollCache() {
5831        initScrollCache();
5832        return mScrollCache;
5833    }
5834
5835    /**
5836     * Set the position of the vertical scroll bar. Should be one of
5837     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5838     * {@link #SCROLLBAR_POSITION_RIGHT}.
5839     *
5840     * @param position Where the vertical scroll bar should be positioned.
5841     */
5842    public void setVerticalScrollbarPosition(int position) {
5843        if (mVerticalScrollbarPosition != position) {
5844            mVerticalScrollbarPosition = position;
5845            computeOpaqueFlags();
5846            resolvePadding();
5847        }
5848    }
5849
5850    /**
5851     * @return The position where the vertical scroll bar will show, if applicable.
5852     * @see #setVerticalScrollbarPosition(int)
5853     */
5854    public int getVerticalScrollbarPosition() {
5855        return mVerticalScrollbarPosition;
5856    }
5857
5858    boolean isOnScrollbar(float x, float y) {
5859        if (mScrollCache == null) {
5860            return false;
5861        }
5862        x += getScrollX();
5863        y += getScrollY();
5864        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5865            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5866            getVerticalScrollBarBounds(null, touchBounds);
5867            if (touchBounds.contains((int) x, (int) y)) {
5868                return true;
5869            }
5870        }
5871        if (isHorizontalScrollBarEnabled()) {
5872            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5873            getHorizontalScrollBarBounds(null, touchBounds);
5874            if (touchBounds.contains((int) x, (int) y)) {
5875                return true;
5876            }
5877        }
5878        return false;
5879    }
5880
5881    boolean isOnScrollbarThumb(float x, float y) {
5882        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5883    }
5884
5885    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5886        if (mScrollCache == null) {
5887            return false;
5888        }
5889        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5890            x += getScrollX();
5891            y += getScrollY();
5892            final Rect bounds = mScrollCache.mScrollBarBounds;
5893            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5894            getVerticalScrollBarBounds(bounds, touchBounds);
5895            final int range = computeVerticalScrollRange();
5896            final int offset = computeVerticalScrollOffset();
5897            final int extent = computeVerticalScrollExtent();
5898            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5899                    extent, range);
5900            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5901                    extent, range, offset);
5902            final int thumbTop = bounds.top + thumbOffset;
5903            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5904            if (x >= touchBounds.left && x <= touchBounds.right
5905                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5906                return true;
5907            }
5908        }
5909        return false;
5910    }
5911
5912    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5913        if (mScrollCache == null) {
5914            return false;
5915        }
5916        if (isHorizontalScrollBarEnabled()) {
5917            x += getScrollX();
5918            y += getScrollY();
5919            final Rect bounds = mScrollCache.mScrollBarBounds;
5920            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5921            getHorizontalScrollBarBounds(bounds, touchBounds);
5922            final int range = computeHorizontalScrollRange();
5923            final int offset = computeHorizontalScrollOffset();
5924            final int extent = computeHorizontalScrollExtent();
5925            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5926                    extent, range);
5927            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5928                    extent, range, offset);
5929            final int thumbLeft = bounds.left + thumbOffset;
5930            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5931            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5932                    && y >= touchBounds.top && y <= touchBounds.bottom) {
5933                return true;
5934            }
5935        }
5936        return false;
5937    }
5938
5939    boolean isDraggingScrollBar() {
5940        return mScrollCache != null
5941                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5942    }
5943
5944    /**
5945     * Sets the state of all scroll indicators.
5946     * <p>
5947     * See {@link #setScrollIndicators(int, int)} for usage information.
5948     *
5949     * @param indicators a bitmask of indicators that should be enabled, or
5950     *                   {@code 0} to disable all indicators
5951     * @see #setScrollIndicators(int, int)
5952     * @see #getScrollIndicators()
5953     * @attr ref android.R.styleable#View_scrollIndicators
5954     */
5955    public void setScrollIndicators(@ScrollIndicators int indicators) {
5956        setScrollIndicators(indicators,
5957                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5958    }
5959
5960    /**
5961     * Sets the state of the scroll indicators specified by the mask. To change
5962     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5963     * <p>
5964     * When a scroll indicator is enabled, it will be displayed if the view
5965     * can scroll in the direction of the indicator.
5966     * <p>
5967     * Multiple indicator types may be enabled or disabled by passing the
5968     * logical OR of the desired types. If multiple types are specified, they
5969     * will all be set to the same enabled state.
5970     * <p>
5971     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5972     *
5973     * @param indicators the indicator direction, or the logical OR of multiple
5974     *             indicator directions. One or more of:
5975     *             <ul>
5976     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5977     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5978     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5979     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5980     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5981     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5982     *             </ul>
5983     * @see #setScrollIndicators(int)
5984     * @see #getScrollIndicators()
5985     * @attr ref android.R.styleable#View_scrollIndicators
5986     */
5987    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5988        // Shift and sanitize mask.
5989        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5990        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5991
5992        // Shift and mask indicators.
5993        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5994        indicators &= mask;
5995
5996        // Merge with non-masked flags.
5997        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5998
5999        if (mPrivateFlags3 != updatedFlags) {
6000            mPrivateFlags3 = updatedFlags;
6001
6002            if (indicators != 0) {
6003                initializeScrollIndicatorsInternal();
6004            }
6005            invalidate();
6006        }
6007    }
6008
6009    /**
6010     * Returns a bitmask representing the enabled scroll indicators.
6011     * <p>
6012     * For example, if the top and left scroll indicators are enabled and all
6013     * other indicators are disabled, the return value will be
6014     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
6015     * <p>
6016     * To check whether the bottom scroll indicator is enabled, use the value
6017     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
6018     *
6019     * @return a bitmask representing the enabled scroll indicators
6020     */
6021    @ScrollIndicators
6022    public int getScrollIndicators() {
6023        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
6024                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
6025    }
6026
6027    ListenerInfo getListenerInfo() {
6028        if (mListenerInfo != null) {
6029            return mListenerInfo;
6030        }
6031        mListenerInfo = new ListenerInfo();
6032        return mListenerInfo;
6033    }
6034
6035    /**
6036     * Register a callback to be invoked when the scroll X or Y positions of
6037     * this view change.
6038     * <p>
6039     * <b>Note:</b> Some views handle scrolling independently from View and may
6040     * have their own separate listeners for scroll-type events. For example,
6041     * {@link android.widget.ListView ListView} allows clients to register an
6042     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
6043     * to listen for changes in list scroll position.
6044     *
6045     * @param l The listener to notify when the scroll X or Y position changes.
6046     * @see android.view.View#getScrollX()
6047     * @see android.view.View#getScrollY()
6048     */
6049    public void setOnScrollChangeListener(OnScrollChangeListener l) {
6050        getListenerInfo().mOnScrollChangeListener = l;
6051    }
6052
6053    /**
6054     * Register a callback to be invoked when focus of this view changed.
6055     *
6056     * @param l The callback that will run.
6057     */
6058    public void setOnFocusChangeListener(OnFocusChangeListener l) {
6059        getListenerInfo().mOnFocusChangeListener = l;
6060    }
6061
6062    /**
6063     * Add a listener that will be called when the bounds of the view change due to
6064     * layout processing.
6065     *
6066     * @param listener The listener that will be called when layout bounds change.
6067     */
6068    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
6069        ListenerInfo li = getListenerInfo();
6070        if (li.mOnLayoutChangeListeners == null) {
6071            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
6072        }
6073        if (!li.mOnLayoutChangeListeners.contains(listener)) {
6074            li.mOnLayoutChangeListeners.add(listener);
6075        }
6076    }
6077
6078    /**
6079     * Remove a listener for layout changes.
6080     *
6081     * @param listener The listener for layout bounds change.
6082     */
6083    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
6084        ListenerInfo li = mListenerInfo;
6085        if (li == null || li.mOnLayoutChangeListeners == null) {
6086            return;
6087        }
6088        li.mOnLayoutChangeListeners.remove(listener);
6089    }
6090
6091    /**
6092     * Add a listener for attach state changes.
6093     *
6094     * This listener will be called whenever this view is attached or detached
6095     * from a window. Remove the listener using
6096     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
6097     *
6098     * @param listener Listener to attach
6099     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
6100     */
6101    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6102        ListenerInfo li = getListenerInfo();
6103        if (li.mOnAttachStateChangeListeners == null) {
6104            li.mOnAttachStateChangeListeners
6105                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
6106        }
6107        li.mOnAttachStateChangeListeners.add(listener);
6108    }
6109
6110    /**
6111     * Remove a listener for attach state changes. The listener will receive no further
6112     * notification of window attach/detach events.
6113     *
6114     * @param listener Listener to remove
6115     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
6116     */
6117    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6118        ListenerInfo li = mListenerInfo;
6119        if (li == null || li.mOnAttachStateChangeListeners == null) {
6120            return;
6121        }
6122        li.mOnAttachStateChangeListeners.remove(listener);
6123    }
6124
6125    /**
6126     * Returns the focus-change callback registered for this view.
6127     *
6128     * @return The callback, or null if one is not registered.
6129     */
6130    public OnFocusChangeListener getOnFocusChangeListener() {
6131        ListenerInfo li = mListenerInfo;
6132        return li != null ? li.mOnFocusChangeListener : null;
6133    }
6134
6135    /**
6136     * Register a callback to be invoked when this view is clicked. If this view is not
6137     * clickable, it becomes clickable.
6138     *
6139     * @param l The callback that will run
6140     *
6141     * @see #setClickable(boolean)
6142     */
6143    public void setOnClickListener(@Nullable OnClickListener l) {
6144        if (!isClickable()) {
6145            setClickable(true);
6146        }
6147        getListenerInfo().mOnClickListener = l;
6148    }
6149
6150    /**
6151     * Return whether this view has an attached OnClickListener.  Returns
6152     * true if there is a listener, false if there is none.
6153     */
6154    public boolean hasOnClickListeners() {
6155        ListenerInfo li = mListenerInfo;
6156        return (li != null && li.mOnClickListener != null);
6157    }
6158
6159    /**
6160     * Register a callback to be invoked when this view is clicked and held. If this view is not
6161     * long clickable, it becomes long clickable.
6162     *
6163     * @param l The callback that will run
6164     *
6165     * @see #setLongClickable(boolean)
6166     */
6167    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6168        if (!isLongClickable()) {
6169            setLongClickable(true);
6170        }
6171        getListenerInfo().mOnLongClickListener = l;
6172    }
6173
6174    /**
6175     * Register a callback to be invoked when this view is context clicked. If the view is not
6176     * context clickable, it becomes context clickable.
6177     *
6178     * @param l The callback that will run
6179     * @see #setContextClickable(boolean)
6180     */
6181    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6182        if (!isContextClickable()) {
6183            setContextClickable(true);
6184        }
6185        getListenerInfo().mOnContextClickListener = l;
6186    }
6187
6188    /**
6189     * Register a callback to be invoked when the context menu for this view is
6190     * being built. If this view is not long clickable, it becomes long clickable.
6191     *
6192     * @param l The callback that will run
6193     *
6194     */
6195    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6196        if (!isLongClickable()) {
6197            setLongClickable(true);
6198        }
6199        getListenerInfo().mOnCreateContextMenuListener = l;
6200    }
6201
6202    /**
6203     * Set an observer to collect stats for each frame rendered for this view.
6204     *
6205     * @hide
6206     */
6207    public void addFrameMetricsListener(Window window,
6208            Window.OnFrameMetricsAvailableListener listener,
6209            Handler handler) {
6210        if (mAttachInfo != null) {
6211            if (mAttachInfo.mThreadedRenderer != null) {
6212                if (mFrameMetricsObservers == null) {
6213                    mFrameMetricsObservers = new ArrayList<>();
6214                }
6215
6216                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6217                        handler.getLooper(), listener);
6218                mFrameMetricsObservers.add(fmo);
6219                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6220            } else {
6221                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6222            }
6223        } else {
6224            if (mFrameMetricsObservers == null) {
6225                mFrameMetricsObservers = new ArrayList<>();
6226            }
6227
6228            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6229                    handler.getLooper(), listener);
6230            mFrameMetricsObservers.add(fmo);
6231        }
6232    }
6233
6234    /**
6235     * Remove observer configured to collect frame stats for this view.
6236     *
6237     * @hide
6238     */
6239    public void removeFrameMetricsListener(
6240            Window.OnFrameMetricsAvailableListener listener) {
6241        ThreadedRenderer renderer = getThreadedRenderer();
6242        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6243        if (fmo == null) {
6244            throw new IllegalArgumentException(
6245                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
6246        }
6247
6248        if (mFrameMetricsObservers != null) {
6249            mFrameMetricsObservers.remove(fmo);
6250            if (renderer != null) {
6251                renderer.removeFrameMetricsObserver(fmo);
6252            }
6253        }
6254    }
6255
6256    private void registerPendingFrameMetricsObservers() {
6257        if (mFrameMetricsObservers != null) {
6258            ThreadedRenderer renderer = getThreadedRenderer();
6259            if (renderer != null) {
6260                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6261                    renderer.addFrameMetricsObserver(fmo);
6262                }
6263            } else {
6264                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6265            }
6266        }
6267    }
6268
6269    private FrameMetricsObserver findFrameMetricsObserver(
6270            Window.OnFrameMetricsAvailableListener listener) {
6271        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6272            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6273            if (observer.mListener == listener) {
6274                return observer;
6275            }
6276        }
6277
6278        return null;
6279    }
6280
6281    /**
6282     * Call this view's OnClickListener, if it is defined.  Performs all normal
6283     * actions associated with clicking: reporting accessibility event, playing
6284     * a sound, etc.
6285     *
6286     * @return True there was an assigned OnClickListener that was called, false
6287     *         otherwise is returned.
6288     */
6289    public boolean performClick() {
6290        final boolean result;
6291        final ListenerInfo li = mListenerInfo;
6292        if (li != null && li.mOnClickListener != null) {
6293            playSoundEffect(SoundEffectConstants.CLICK);
6294            li.mOnClickListener.onClick(this);
6295            result = true;
6296        } else {
6297            result = false;
6298        }
6299
6300        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6301
6302        notifyEnterOrExitForAutoFillIfNeeded(true);
6303
6304        return result;
6305    }
6306
6307    /**
6308     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6309     * this only calls the listener, and does not do any associated clicking
6310     * actions like reporting an accessibility event.
6311     *
6312     * @return True there was an assigned OnClickListener that was called, false
6313     *         otherwise is returned.
6314     */
6315    public boolean callOnClick() {
6316        ListenerInfo li = mListenerInfo;
6317        if (li != null && li.mOnClickListener != null) {
6318            li.mOnClickListener.onClick(this);
6319            return true;
6320        }
6321        return false;
6322    }
6323
6324    /**
6325     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6326     * context menu if the OnLongClickListener did not consume the event.
6327     *
6328     * @return {@code true} if one of the above receivers consumed the event,
6329     *         {@code false} otherwise
6330     */
6331    public boolean performLongClick() {
6332        return performLongClickInternal(mLongClickX, mLongClickY);
6333    }
6334
6335    /**
6336     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6337     * context menu if the OnLongClickListener did not consume the event,
6338     * anchoring it to an (x,y) coordinate.
6339     *
6340     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6341     *          to disable anchoring
6342     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6343     *          to disable anchoring
6344     * @return {@code true} if one of the above receivers consumed the event,
6345     *         {@code false} otherwise
6346     */
6347    public boolean performLongClick(float x, float y) {
6348        mLongClickX = x;
6349        mLongClickY = y;
6350        final boolean handled = performLongClick();
6351        mLongClickX = Float.NaN;
6352        mLongClickY = Float.NaN;
6353        return handled;
6354    }
6355
6356    /**
6357     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6358     * context menu if the OnLongClickListener did not consume the event,
6359     * optionally anchoring it to an (x,y) coordinate.
6360     *
6361     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6362     *          to disable anchoring
6363     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6364     *          to disable anchoring
6365     * @return {@code true} if one of the above receivers consumed the event,
6366     *         {@code false} otherwise
6367     */
6368    private boolean performLongClickInternal(float x, float y) {
6369        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6370
6371        boolean handled = false;
6372        final ListenerInfo li = mListenerInfo;
6373        if (li != null && li.mOnLongClickListener != null) {
6374            handled = li.mOnLongClickListener.onLongClick(View.this);
6375        }
6376        if (!handled) {
6377            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6378            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6379        }
6380        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6381            if (!handled) {
6382                handled = showLongClickTooltip((int) x, (int) y);
6383            }
6384        }
6385        if (handled) {
6386            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6387        }
6388        return handled;
6389    }
6390
6391    /**
6392     * Call this view's OnContextClickListener, if it is defined.
6393     *
6394     * @param x the x coordinate of the context click
6395     * @param y the y coordinate of the context click
6396     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6397     *         otherwise.
6398     */
6399    public boolean performContextClick(float x, float y) {
6400        return performContextClick();
6401    }
6402
6403    /**
6404     * Call this view's OnContextClickListener, if it is defined.
6405     *
6406     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6407     *         otherwise.
6408     */
6409    public boolean performContextClick() {
6410        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6411
6412        boolean handled = false;
6413        ListenerInfo li = mListenerInfo;
6414        if (li != null && li.mOnContextClickListener != null) {
6415            handled = li.mOnContextClickListener.onContextClick(View.this);
6416        }
6417        if (handled) {
6418            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6419        }
6420        return handled;
6421    }
6422
6423    /**
6424     * Performs button-related actions during a touch down event.
6425     *
6426     * @param event The event.
6427     * @return True if the down was consumed.
6428     *
6429     * @hide
6430     */
6431    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6432        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6433            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6434            showContextMenu(event.getX(), event.getY());
6435            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6436            return true;
6437        }
6438        return false;
6439    }
6440
6441    /**
6442     * Shows the context menu for this view.
6443     *
6444     * @return {@code true} if the context menu was shown, {@code false}
6445     *         otherwise
6446     * @see #showContextMenu(float, float)
6447     */
6448    public boolean showContextMenu() {
6449        return getParent().showContextMenuForChild(this);
6450    }
6451
6452    /**
6453     * Shows the context menu for this view anchored to the specified
6454     * view-relative coordinate.
6455     *
6456     * @param x the X coordinate in pixels relative to the view to which the
6457     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6458     * @param y the Y coordinate in pixels relative to the view to which the
6459     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6460     * @return {@code true} if the context menu was shown, {@code false}
6461     *         otherwise
6462     */
6463    public boolean showContextMenu(float x, float y) {
6464        return getParent().showContextMenuForChild(this, x, y);
6465    }
6466
6467    /**
6468     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6469     *
6470     * @param callback Callback that will control the lifecycle of the action mode
6471     * @return The new action mode if it is started, null otherwise
6472     *
6473     * @see ActionMode
6474     * @see #startActionMode(android.view.ActionMode.Callback, int)
6475     */
6476    public ActionMode startActionMode(ActionMode.Callback callback) {
6477        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6478    }
6479
6480    /**
6481     * Start an action mode with the given type.
6482     *
6483     * @param callback Callback that will control the lifecycle of the action mode
6484     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6485     * @return The new action mode if it is started, null otherwise
6486     *
6487     * @see ActionMode
6488     */
6489    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6490        ViewParent parent = getParent();
6491        if (parent == null) return null;
6492        try {
6493            return parent.startActionModeForChild(this, callback, type);
6494        } catch (AbstractMethodError ame) {
6495            // Older implementations of custom views might not implement this.
6496            return parent.startActionModeForChild(this, callback);
6497        }
6498    }
6499
6500    /**
6501     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6502     * Context, creating a unique View identifier to retrieve the result.
6503     *
6504     * @param intent The Intent to be started.
6505     * @param requestCode The request code to use.
6506     * @hide
6507     */
6508    public void startActivityForResult(Intent intent, int requestCode) {
6509        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6510        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6511    }
6512
6513    /**
6514     * If this View corresponds to the calling who, dispatches the activity result.
6515     * @param who The identifier for the targeted View to receive the result.
6516     * @param requestCode The integer request code originally supplied to
6517     *                    startActivityForResult(), allowing you to identify who this
6518     *                    result came from.
6519     * @param resultCode The integer result code returned by the child activity
6520     *                   through its setResult().
6521     * @param data An Intent, which can return result data to the caller
6522     *               (various data can be attached to Intent "extras").
6523     * @return {@code true} if the activity result was dispatched.
6524     * @hide
6525     */
6526    public boolean dispatchActivityResult(
6527            String who, int requestCode, int resultCode, Intent data) {
6528        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6529            onActivityResult(requestCode, resultCode, data);
6530            mStartActivityRequestWho = null;
6531            return true;
6532        }
6533        return false;
6534    }
6535
6536    /**
6537     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6538     *
6539     * @param requestCode The integer request code originally supplied to
6540     *                    startActivityForResult(), allowing you to identify who this
6541     *                    result came from.
6542     * @param resultCode The integer result code returned by the child activity
6543     *                   through its setResult().
6544     * @param data An Intent, which can return result data to the caller
6545     *               (various data can be attached to Intent "extras").
6546     * @hide
6547     */
6548    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6549        // Do nothing.
6550    }
6551
6552    /**
6553     * Register a callback to be invoked when a hardware key is pressed in this view.
6554     * Key presses in software input methods will generally not trigger the methods of
6555     * this listener.
6556     * @param l the key listener to attach to this view
6557     */
6558    public void setOnKeyListener(OnKeyListener l) {
6559        getListenerInfo().mOnKeyListener = l;
6560    }
6561
6562    /**
6563     * Register a callback to be invoked when a touch event is sent to this view.
6564     * @param l the touch listener to attach to this view
6565     */
6566    public void setOnTouchListener(OnTouchListener l) {
6567        getListenerInfo().mOnTouchListener = l;
6568    }
6569
6570    /**
6571     * Register a callback to be invoked when a generic motion event is sent to this view.
6572     * @param l the generic motion listener to attach to this view
6573     */
6574    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6575        getListenerInfo().mOnGenericMotionListener = l;
6576    }
6577
6578    /**
6579     * Register a callback to be invoked when a hover event is sent to this view.
6580     * @param l the hover listener to attach to this view
6581     */
6582    public void setOnHoverListener(OnHoverListener l) {
6583        getListenerInfo().mOnHoverListener = l;
6584    }
6585
6586    /**
6587     * Register a drag event listener callback object for this View. The parameter is
6588     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6589     * View, the system calls the
6590     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6591     * @param l An implementation of {@link android.view.View.OnDragListener}.
6592     */
6593    public void setOnDragListener(OnDragListener l) {
6594        getListenerInfo().mOnDragListener = l;
6595    }
6596
6597    /**
6598     * Give this view focus. This will cause
6599     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6600     *
6601     * Note: this does not check whether this {@link View} should get focus, it just
6602     * gives it focus no matter what.  It should only be called internally by framework
6603     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6604     *
6605     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6606     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6607     *        focus moved when requestFocus() is called. It may not always
6608     *        apply, in which case use the default View.FOCUS_DOWN.
6609     * @param previouslyFocusedRect The rectangle of the view that had focus
6610     *        prior in this View's coordinate system.
6611     */
6612    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6613        if (DBG) {
6614            System.out.println(this + " requestFocus()");
6615        }
6616
6617        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6618            mPrivateFlags |= PFLAG_FOCUSED;
6619
6620            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6621
6622            if (mParent != null) {
6623                mParent.requestChildFocus(this, this);
6624                updateFocusedInCluster(oldFocus, direction);
6625            }
6626
6627            if (mAttachInfo != null) {
6628                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6629            }
6630
6631            onFocusChanged(true, direction, previouslyFocusedRect);
6632            refreshDrawableState();
6633        }
6634    }
6635
6636    /**
6637     * Sets this view's preference for reveal behavior when it gains focus.
6638     *
6639     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6640     * this view would prefer to be brought fully into view when it gains focus.
6641     * For example, a text field that a user is meant to type into. Other views such
6642     * as scrolling containers may prefer to opt-out of this behavior.</p>
6643     *
6644     * <p>The default value for views is true, though subclasses may change this
6645     * based on their preferred behavior.</p>
6646     *
6647     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6648     *
6649     * @see #getRevealOnFocusHint()
6650     */
6651    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6652        if (revealOnFocus) {
6653            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6654        } else {
6655            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6656        }
6657    }
6658
6659    /**
6660     * Returns this view's preference for reveal behavior when it gains focus.
6661     *
6662     * <p>When this method returns true for a child view requesting focus, ancestor
6663     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6664     * should make a best effort to make the newly focused child fully visible to the user.
6665     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6666     * other properties affecting visibility to the user as part of the focus change.</p>
6667     *
6668     * @return true if this view would prefer to become fully visible when it gains focus,
6669     *         false if it would prefer not to disrupt scroll positioning
6670     *
6671     * @see #setRevealOnFocusHint(boolean)
6672     */
6673    public final boolean getRevealOnFocusHint() {
6674        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6675    }
6676
6677    /**
6678     * Populates <code>outRect</code> with the hotspot bounds. By default,
6679     * the hotspot bounds are identical to the screen bounds.
6680     *
6681     * @param outRect rect to populate with hotspot bounds
6682     * @hide Only for internal use by views and widgets.
6683     */
6684    public void getHotspotBounds(Rect outRect) {
6685        final Drawable background = getBackground();
6686        if (background != null) {
6687            background.getHotspotBounds(outRect);
6688        } else {
6689            getBoundsOnScreen(outRect);
6690        }
6691    }
6692
6693    /**
6694     * Request that a rectangle of this view be visible on the screen,
6695     * scrolling if necessary just enough.
6696     *
6697     * <p>A View should call this if it maintains some notion of which part
6698     * of its content is interesting.  For example, a text editing view
6699     * should call this when its cursor moves.
6700     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6701     * It should not be affected by which part of the View is currently visible or its scroll
6702     * position.
6703     *
6704     * @param rectangle The rectangle in the View's content coordinate space
6705     * @return Whether any parent scrolled.
6706     */
6707    public boolean requestRectangleOnScreen(Rect rectangle) {
6708        return requestRectangleOnScreen(rectangle, false);
6709    }
6710
6711    /**
6712     * Request that a rectangle of this view be visible on the screen,
6713     * scrolling if necessary just enough.
6714     *
6715     * <p>A View should call this if it maintains some notion of which part
6716     * of its content is interesting.  For example, a text editing view
6717     * should call this when its cursor moves.
6718     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6719     * It should not be affected by which part of the View is currently visible or its scroll
6720     * position.
6721     * <p>When <code>immediate</code> is set to true, scrolling will not be
6722     * animated.
6723     *
6724     * @param rectangle The rectangle in the View's content coordinate space
6725     * @param immediate True to forbid animated scrolling, false otherwise
6726     * @return Whether any parent scrolled.
6727     */
6728    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6729        if (mParent == null) {
6730            return false;
6731        }
6732
6733        View child = this;
6734
6735        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6736        position.set(rectangle);
6737
6738        ViewParent parent = mParent;
6739        boolean scrolled = false;
6740        while (parent != null) {
6741            rectangle.set((int) position.left, (int) position.top,
6742                    (int) position.right, (int) position.bottom);
6743
6744            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6745
6746            if (!(parent instanceof View)) {
6747                break;
6748            }
6749
6750            // move it from child's content coordinate space to parent's content coordinate space
6751            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6752
6753            child = (View) parent;
6754            parent = child.getParent();
6755        }
6756
6757        return scrolled;
6758    }
6759
6760    /**
6761     * Called when this view wants to give up focus. If focus is cleared
6762     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6763     * <p>
6764     * <strong>Note:</strong> When a View clears focus the framework is trying
6765     * to give focus to the first focusable View from the top. Hence, if this
6766     * View is the first from the top that can take focus, then all callbacks
6767     * related to clearing focus will be invoked after which the framework will
6768     * give focus to this view.
6769     * </p>
6770     */
6771    public void clearFocus() {
6772        if (DBG) {
6773            System.out.println(this + " clearFocus()");
6774        }
6775
6776        clearFocusInternal(null, true, true);
6777    }
6778
6779    /**
6780     * Clears focus from the view, optionally propagating the change up through
6781     * the parent hierarchy and requesting that the root view place new focus.
6782     *
6783     * @param propagate whether to propagate the change up through the parent
6784     *            hierarchy
6785     * @param refocus when propagate is true, specifies whether to request the
6786     *            root view place new focus
6787     */
6788    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6789        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6790            mPrivateFlags &= ~PFLAG_FOCUSED;
6791
6792            if (propagate && mParent != null) {
6793                mParent.clearChildFocus(this);
6794            }
6795
6796            onFocusChanged(false, 0, null);
6797            refreshDrawableState();
6798
6799            if (propagate && (!refocus || !rootViewRequestFocus())) {
6800                notifyGlobalFocusCleared(this);
6801            }
6802        }
6803    }
6804
6805    void notifyGlobalFocusCleared(View oldFocus) {
6806        if (oldFocus != null && mAttachInfo != null) {
6807            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6808        }
6809    }
6810
6811    boolean rootViewRequestFocus() {
6812        final View root = getRootView();
6813        return root != null && root.requestFocus();
6814    }
6815
6816    /**
6817     * Called internally by the view system when a new view is getting focus.
6818     * This is what clears the old focus.
6819     * <p>
6820     * <b>NOTE:</b> The parent view's focused child must be updated manually
6821     * after calling this method. Otherwise, the view hierarchy may be left in
6822     * an inconstent state.
6823     */
6824    void unFocus(View focused) {
6825        if (DBG) {
6826            System.out.println(this + " unFocus()");
6827        }
6828
6829        clearFocusInternal(focused, false, false);
6830    }
6831
6832    /**
6833     * Returns true if this view has focus itself, or is the ancestor of the
6834     * view that has focus.
6835     *
6836     * @return True if this view has or contains focus, false otherwise.
6837     */
6838    @ViewDebug.ExportedProperty(category = "focus")
6839    public boolean hasFocus() {
6840        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6841    }
6842
6843    /**
6844     * Returns true if this view is focusable or if it contains a reachable View
6845     * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6846     * is a view whose parents do not block descendants focus.
6847     * Only {@link #VISIBLE} views are considered focusable.
6848     *
6849     * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6850     * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6851     * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6852     * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6853     * {@code false} for views not explicitly marked as focusable.
6854     * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6855     * behavior.</p>
6856     *
6857     * @return {@code true} if the view is focusable or if the view contains a focusable
6858     *         view, {@code false} otherwise
6859     *
6860     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6861     * @see ViewGroup#getTouchscreenBlocksFocus()
6862     * @see #hasExplicitFocusable()
6863     */
6864    public boolean hasFocusable() {
6865        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6866    }
6867
6868    /**
6869     * Returns true if this view is focusable or if it contains a reachable View
6870     * for which {@link #hasExplicitFocusable()} returns {@code true}.
6871     * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6872     * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6873     * {@link #FOCUSABLE} are considered focusable.
6874     *
6875     * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6876     * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6877     * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6878     * to focusable will not.</p>
6879     *
6880     * @return {@code true} if the view is focusable or if the view contains a focusable
6881     *         view, {@code false} otherwise
6882     *
6883     * @see #hasFocusable()
6884     */
6885    public boolean hasExplicitFocusable() {
6886        return hasFocusable(false, true);
6887    }
6888
6889    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6890        if (!isFocusableInTouchMode()) {
6891            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6892                final ViewGroup g = (ViewGroup) p;
6893                if (g.shouldBlockFocusForTouchscreen()) {
6894                    return false;
6895                }
6896            }
6897        }
6898
6899        // Invisible and gone views are never focusable.
6900        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6901            return false;
6902        }
6903
6904        // Only use effective focusable value when allowed.
6905        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6906            return true;
6907        }
6908
6909        return false;
6910    }
6911
6912    /**
6913     * Called by the view system when the focus state of this view changes.
6914     * When the focus change event is caused by directional navigation, direction
6915     * and previouslyFocusedRect provide insight into where the focus is coming from.
6916     * When overriding, be sure to call up through to the super class so that
6917     * the standard focus handling will occur.
6918     *
6919     * @param gainFocus True if the View has focus; false otherwise.
6920     * @param direction The direction focus has moved when requestFocus()
6921     *                  is called to give this view focus. Values are
6922     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6923     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6924     *                  It may not always apply, in which case use the default.
6925     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6926     *        system, of the previously focused view.  If applicable, this will be
6927     *        passed in as finer grained information about where the focus is coming
6928     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6929     */
6930    @CallSuper
6931    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6932            @Nullable Rect previouslyFocusedRect) {
6933        if (gainFocus) {
6934            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6935        } else {
6936            notifyViewAccessibilityStateChangedIfNeeded(
6937                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6938        }
6939
6940        // Here we check whether we still need the default focus highlight, and switch it on/off.
6941        switchDefaultFocusHighlight();
6942
6943        InputMethodManager imm = InputMethodManager.peekInstance();
6944        if (!gainFocus) {
6945            if (isPressed()) {
6946                setPressed(false);
6947            }
6948            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6949                imm.focusOut(this);
6950            }
6951            onFocusLost();
6952        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6953            imm.focusIn(this);
6954        }
6955
6956        invalidate(true);
6957        ListenerInfo li = mListenerInfo;
6958        if (li != null && li.mOnFocusChangeListener != null) {
6959            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6960        }
6961
6962        if (mAttachInfo != null) {
6963            mAttachInfo.mKeyDispatchState.reset(this);
6964        }
6965
6966        notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6967    }
6968
6969    private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6970        if (isAutofillable() && isAttachedToWindow()) {
6971            AutofillManager afm = getAutofillManager();
6972            if (afm != null) {
6973                if (enter && hasWindowFocus() && isFocused()) {
6974                    // We have not been laid out yet, hence cannot evaluate
6975                    // whether this view is visible to the user, we will do
6976                    // the evaluation once layout is complete.
6977                    if (!isLaidOut()) {
6978                        mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
6979                    } else if (isVisibleToUser()) {
6980                        afm.notifyViewEntered(this);
6981                    }
6982                } else if (!hasWindowFocus() || !isFocused()) {
6983                    afm.notifyViewExited(this);
6984                }
6985            }
6986        }
6987    }
6988
6989    /**
6990     * Sends an accessibility event of the given type. If accessibility is
6991     * not enabled this method has no effect. The default implementation calls
6992     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6993     * to populate information about the event source (this View), then calls
6994     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6995     * populate the text content of the event source including its descendants,
6996     * and last calls
6997     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6998     * on its parent to request sending of the event to interested parties.
6999     * <p>
7000     * If an {@link AccessibilityDelegate} has been specified via calling
7001     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7002     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
7003     * responsible for handling this call.
7004     * </p>
7005     *
7006     * @param eventType The type of the event to send, as defined by several types from
7007     * {@link android.view.accessibility.AccessibilityEvent}, such as
7008     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
7009     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
7010     *
7011     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7012     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7013     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
7014     * @see AccessibilityDelegate
7015     */
7016    public void sendAccessibilityEvent(int eventType) {
7017        if (mAccessibilityDelegate != null) {
7018            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
7019        } else {
7020            sendAccessibilityEventInternal(eventType);
7021        }
7022    }
7023
7024    /**
7025     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
7026     * {@link AccessibilityEvent} to make an announcement which is related to some
7027     * sort of a context change for which none of the events representing UI transitions
7028     * is a good fit. For example, announcing a new page in a book. If accessibility
7029     * is not enabled this method does nothing.
7030     *
7031     * @param text The announcement text.
7032     */
7033    public void announceForAccessibility(CharSequence text) {
7034        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
7035            AccessibilityEvent event = AccessibilityEvent.obtain(
7036                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
7037            onInitializeAccessibilityEvent(event);
7038            event.getText().add(text);
7039            event.setContentDescription(null);
7040            mParent.requestSendAccessibilityEvent(this, event);
7041        }
7042    }
7043
7044    /**
7045     * @see #sendAccessibilityEvent(int)
7046     *
7047     * Note: Called from the default {@link AccessibilityDelegate}.
7048     *
7049     * @hide
7050     */
7051    public void sendAccessibilityEventInternal(int eventType) {
7052        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
7053            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
7054        }
7055    }
7056
7057    /**
7058     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
7059     * takes as an argument an empty {@link AccessibilityEvent} and does not
7060     * perform a check whether accessibility is enabled.
7061     * <p>
7062     * If an {@link AccessibilityDelegate} has been specified via calling
7063     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7064     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
7065     * is responsible for handling this call.
7066     * </p>
7067     *
7068     * @param event The event to send.
7069     *
7070     * @see #sendAccessibilityEvent(int)
7071     */
7072    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
7073        if (mAccessibilityDelegate != null) {
7074            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
7075        } else {
7076            sendAccessibilityEventUncheckedInternal(event);
7077        }
7078    }
7079
7080    /**
7081     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
7082     *
7083     * Note: Called from the default {@link AccessibilityDelegate}.
7084     *
7085     * @hide
7086     */
7087    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
7088        if (!isShown()) {
7089            return;
7090        }
7091        onInitializeAccessibilityEvent(event);
7092        // Only a subset of accessibility events populates text content.
7093        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
7094            dispatchPopulateAccessibilityEvent(event);
7095        }
7096        // In the beginning we called #isShown(), so we know that getParent() is not null.
7097        ViewParent parent = getParent();
7098        if (parent != null) {
7099            getParent().requestSendAccessibilityEvent(this, event);
7100        }
7101    }
7102
7103    /**
7104     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
7105     * to its children for adding their text content to the event. Note that the
7106     * event text is populated in a separate dispatch path since we add to the
7107     * event not only the text of the source but also the text of all its descendants.
7108     * A typical implementation will call
7109     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
7110     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7111     * on each child. Override this method if custom population of the event text
7112     * content is required.
7113     * <p>
7114     * If an {@link AccessibilityDelegate} has been specified via calling
7115     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7116     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
7117     * is responsible for handling this call.
7118     * </p>
7119     * <p>
7120     * <em>Note:</em> Accessibility events of certain types are not dispatched for
7121     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
7122     * </p>
7123     *
7124     * @param event The event.
7125     *
7126     * @return True if the event population was completed.
7127     */
7128    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
7129        if (mAccessibilityDelegate != null) {
7130            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
7131        } else {
7132            return dispatchPopulateAccessibilityEventInternal(event);
7133        }
7134    }
7135
7136    /**
7137     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7138     *
7139     * Note: Called from the default {@link AccessibilityDelegate}.
7140     *
7141     * @hide
7142     */
7143    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7144        onPopulateAccessibilityEvent(event);
7145        return false;
7146    }
7147
7148    /**
7149     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7150     * giving a chance to this View to populate the accessibility event with its
7151     * text content. While this method is free to modify event
7152     * attributes other than text content, doing so should normally be performed in
7153     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
7154     * <p>
7155     * Example: Adding formatted date string to an accessibility event in addition
7156     *          to the text added by the super implementation:
7157     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7158     *     super.onPopulateAccessibilityEvent(event);
7159     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
7160     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
7161     *         mCurrentDate.getTimeInMillis(), flags);
7162     *     event.getText().add(selectedDateUtterance);
7163     * }</pre>
7164     * <p>
7165     * If an {@link AccessibilityDelegate} has been specified via calling
7166     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7167     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7168     * is responsible for handling this call.
7169     * </p>
7170     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7171     * information to the event, in case the default implementation has basic information to add.
7172     * </p>
7173     *
7174     * @param event The accessibility event which to populate.
7175     *
7176     * @see #sendAccessibilityEvent(int)
7177     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7178     */
7179    @CallSuper
7180    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7181        if (mAccessibilityDelegate != null) {
7182            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7183        } else {
7184            onPopulateAccessibilityEventInternal(event);
7185        }
7186    }
7187
7188    /**
7189     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7190     *
7191     * Note: Called from the default {@link AccessibilityDelegate}.
7192     *
7193     * @hide
7194     */
7195    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7196    }
7197
7198    /**
7199     * Initializes an {@link AccessibilityEvent} with information about
7200     * this View which is the event source. In other words, the source of
7201     * an accessibility event is the view whose state change triggered firing
7202     * the event.
7203     * <p>
7204     * Example: Setting the password property of an event in addition
7205     *          to properties set by the super implementation:
7206     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7207     *     super.onInitializeAccessibilityEvent(event);
7208     *     event.setPassword(true);
7209     * }</pre>
7210     * <p>
7211     * If an {@link AccessibilityDelegate} has been specified via calling
7212     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7213     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7214     * is responsible for handling this call.
7215     * </p>
7216     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7217     * information to the event, in case the default implementation has basic information to add.
7218     * </p>
7219     * @param event The event to initialize.
7220     *
7221     * @see #sendAccessibilityEvent(int)
7222     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7223     */
7224    @CallSuper
7225    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7226        if (mAccessibilityDelegate != null) {
7227            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7228        } else {
7229            onInitializeAccessibilityEventInternal(event);
7230        }
7231    }
7232
7233    /**
7234     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7235     *
7236     * Note: Called from the default {@link AccessibilityDelegate}.
7237     *
7238     * @hide
7239     */
7240    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7241        event.setSource(this);
7242        event.setClassName(getAccessibilityClassName());
7243        event.setPackageName(getContext().getPackageName());
7244        event.setEnabled(isEnabled());
7245        event.setContentDescription(mContentDescription);
7246
7247        switch (event.getEventType()) {
7248            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7249                ArrayList<View> focusablesTempList = (mAttachInfo != null)
7250                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7251                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7252                event.setItemCount(focusablesTempList.size());
7253                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7254                if (mAttachInfo != null) {
7255                    focusablesTempList.clear();
7256                }
7257            } break;
7258            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7259                CharSequence text = getIterableTextForAccessibility();
7260                if (text != null && text.length() > 0) {
7261                    event.setFromIndex(getAccessibilitySelectionStart());
7262                    event.setToIndex(getAccessibilitySelectionEnd());
7263                    event.setItemCount(text.length());
7264                }
7265            } break;
7266        }
7267    }
7268
7269    /**
7270     * Returns an {@link AccessibilityNodeInfo} representing this view from the
7271     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7272     * This method is responsible for obtaining an accessibility node info from a
7273     * pool of reusable instances and calling
7274     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7275     * initialize the former.
7276     * <p>
7277     * Note: The client is responsible for recycling the obtained instance by calling
7278     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7279     * </p>
7280     *
7281     * @return A populated {@link AccessibilityNodeInfo}.
7282     *
7283     * @see AccessibilityNodeInfo
7284     */
7285    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7286        if (mAccessibilityDelegate != null) {
7287            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7288        } else {
7289            return createAccessibilityNodeInfoInternal();
7290        }
7291    }
7292
7293    /**
7294     * @see #createAccessibilityNodeInfo()
7295     *
7296     * @hide
7297     */
7298    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7299        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7300        if (provider != null) {
7301            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7302        } else {
7303            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7304            onInitializeAccessibilityNodeInfo(info);
7305            return info;
7306        }
7307    }
7308
7309    /**
7310     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7311     * The base implementation sets:
7312     * <ul>
7313     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7314     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7315     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7316     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7317     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7318     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7319     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7320     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7321     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7322     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7323     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7324     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7325     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7326     * </ul>
7327     * <p>
7328     * Subclasses should override this method, call the super implementation,
7329     * and set additional attributes.
7330     * </p>
7331     * <p>
7332     * If an {@link AccessibilityDelegate} has been specified via calling
7333     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7334     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7335     * is responsible for handling this call.
7336     * </p>
7337     *
7338     * @param info The instance to initialize.
7339     */
7340    @CallSuper
7341    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7342        if (mAccessibilityDelegate != null) {
7343            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7344        } else {
7345            onInitializeAccessibilityNodeInfoInternal(info);
7346        }
7347    }
7348
7349    /**
7350     * Gets the location of this view in screen coordinates.
7351     *
7352     * @param outRect The output location
7353     * @hide
7354     */
7355    public void getBoundsOnScreen(Rect outRect) {
7356        getBoundsOnScreen(outRect, false);
7357    }
7358
7359    /**
7360     * Gets the location of this view in screen coordinates.
7361     *
7362     * @param outRect The output location
7363     * @param clipToParent Whether to clip child bounds to the parent ones.
7364     * @hide
7365     */
7366    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7367        if (mAttachInfo == null) {
7368            return;
7369        }
7370
7371        RectF position = mAttachInfo.mTmpTransformRect;
7372        position.set(0, 0, mRight - mLeft, mBottom - mTop);
7373        mapRectFromViewToScreenCoords(position, clipToParent);
7374        outRect.set(Math.round(position.left), Math.round(position.top),
7375                Math.round(position.right), Math.round(position.bottom));
7376    }
7377
7378    /**
7379     * Map a rectangle from view-relative coordinates to screen-relative coordinates
7380     *
7381     * @param rect The rectangle to be mapped
7382     * @param clipToParent Whether to clip child bounds to the parent ones.
7383     * @hide
7384     */
7385    public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
7386        if (!hasIdentityMatrix()) {
7387            getMatrix().mapRect(rect);
7388        }
7389
7390        rect.offset(mLeft, mTop);
7391
7392        ViewParent parent = mParent;
7393        while (parent instanceof View) {
7394            View parentView = (View) parent;
7395
7396            rect.offset(-parentView.mScrollX, -parentView.mScrollY);
7397
7398            if (clipToParent) {
7399                rect.left = Math.max(rect.left, 0);
7400                rect.top = Math.max(rect.top, 0);
7401                rect.right = Math.min(rect.right, parentView.getWidth());
7402                rect.bottom = Math.min(rect.bottom, parentView.getHeight());
7403            }
7404
7405            if (!parentView.hasIdentityMatrix()) {
7406                parentView.getMatrix().mapRect(rect);
7407            }
7408
7409            rect.offset(parentView.mLeft, parentView.mTop);
7410
7411            parent = parentView.mParent;
7412        }
7413
7414        if (parent instanceof ViewRootImpl) {
7415            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7416            rect.offset(0, -viewRootImpl.mCurScrollY);
7417        }
7418
7419        rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7420    }
7421
7422    /**
7423     * Return the class name of this object to be used for accessibility purposes.
7424     * Subclasses should only override this if they are implementing something that
7425     * should be seen as a completely new class of view when used by accessibility,
7426     * unrelated to the class it is deriving from.  This is used to fill in
7427     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7428     */
7429    public CharSequence getAccessibilityClassName() {
7430        return View.class.getName();
7431    }
7432
7433    /**
7434     * Called when assist structure is being retrieved from a view as part of
7435     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7436     * @param structure Fill in with structured view data.  The default implementation
7437     * fills in all data that can be inferred from the view itself.
7438     */
7439    public void onProvideStructure(ViewStructure structure) {
7440        onProvideStructureForAssistOrAutofill(structure, false, 0);
7441    }
7442
7443    /**
7444     * Populates a {@link ViewStructure} to fullfil an autofill request.
7445     *
7446     * <p>The structure should contain at least the following properties:
7447     * <ul>
7448     *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
7449     *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
7450     *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
7451     *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
7452     * </ul>
7453     *
7454     * <p>It's also recommended to set the following properties - the more properties the structure
7455     * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
7456     * using the structure:
7457     *
7458     * <ul>
7459     *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
7460     *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
7461     *       view can only be filled with predefined values (typically used when the autofill type
7462     *       is {@link #AUTOFILL_TYPE_LIST}).
7463     *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
7464     *   <li>Class name ({@link ViewStructure#setClassName(String)}).
7465     *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
7466     *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
7467     *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
7468     *       opacity ({@link ViewStructure#setOpaque(boolean)}).
7469     *   <li>For views representing text fields, text properties such as the text itself
7470     *       ({@link ViewStructure#setText(CharSequence)}), text hints
7471     *       ({@link ViewStructure#setHint(CharSequence)}, input type
7472     *       ({@link ViewStructure#setInputType(int)}),
7473     *   <li>For views representing HTML nodes, its web domain
7474     *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
7475     *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
7476     * </ul>
7477     *
7478     * <p>The default implementation of this method already sets most of these properties based on
7479     * related {@link View} methods (for example, the autofill id is set using
7480     * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
7481     * and views in the standard Android widgets library also override it to set their
7482     * relevant properties (for example, {@link android.widget.TextView} already sets the text
7483     * properties), so it's recommended to only override this method
7484     * (and call {@code super.onProvideAutofillStructure()}) when:
7485     *
7486     * <ul>
7487     *   <li>The view contents does not include PII (Personally Identifiable Information), so it
7488     *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7489     *   <li>The view can only be autofilled with predefined options, so it can call
7490     *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
7491     * </ul>
7492     *
7493     * <p><b>Note:</b> The {@code left} and {@code top} values set in
7494     * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
7495     * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
7496     *
7497     * <p>Views support the Autofill Framework mainly by:
7498     * <ul>
7499     *   <li>Providing the metadata defining what the view means and how it can be autofilled.
7500     *   <li>Notifying the Android System when the view value changed by calling
7501     *       {@link AutofillManager#notifyValueChanged(View)}.
7502     *   <li>Implementing the methods that autofill the view.
7503     * </ul>
7504     * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
7505     * for the latter.
7506     *
7507     * @param structure fill in with structured view data for autofill purposes.
7508     * @param flags optional flags.
7509     *
7510     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7511     */
7512    public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
7513        onProvideStructureForAssistOrAutofill(structure, true, flags);
7514    }
7515
7516    private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7517            boolean forAutofill, @AutofillFlags int flags) {
7518        final int id = mID;
7519        if (id != NO_ID && !isViewIdGenerated(id)) {
7520            String pkg, type, entry;
7521            try {
7522                final Resources res = getResources();
7523                entry = res.getResourceEntryName(id);
7524                type = res.getResourceTypeName(id);
7525                pkg = res.getResourcePackageName(id);
7526            } catch (Resources.NotFoundException e) {
7527                entry = type = pkg = null;
7528            }
7529            structure.setId(id, pkg, type, entry);
7530        } else {
7531            structure.setId(id, null, null, null);
7532        }
7533
7534        if (forAutofill) {
7535            final @AutofillType int autofillType = getAutofillType();
7536            // Don't need to fill autofill info if view does not support it.
7537            // For example, only TextViews that are editable support autofill
7538            if (autofillType != AUTOFILL_TYPE_NONE) {
7539                structure.setAutofillType(autofillType);
7540                structure.setAutofillHints(getAutofillHints());
7541                structure.setAutofillValue(getAutofillValue());
7542            }
7543        }
7544
7545        int ignoredParentLeft = 0;
7546        int ignoredParentTop = 0;
7547        if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
7548            View parentGroup = null;
7549
7550            ViewParent viewParent = getParent();
7551            if (viewParent instanceof View) {
7552                parentGroup = (View) viewParent;
7553            }
7554
7555            while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
7556                ignoredParentLeft += parentGroup.mLeft;
7557                ignoredParentTop += parentGroup.mTop;
7558
7559                viewParent = parentGroup.getParent();
7560                if (viewParent instanceof View) {
7561                    parentGroup = (View) viewParent;
7562                } else {
7563                    break;
7564                }
7565            }
7566        }
7567
7568        structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
7569                mRight - mLeft, mBottom - mTop);
7570        if (!forAutofill) {
7571            if (!hasIdentityMatrix()) {
7572                structure.setTransformation(getMatrix());
7573            }
7574            structure.setElevation(getZ());
7575        }
7576        structure.setVisibility(getVisibility());
7577        structure.setEnabled(isEnabled());
7578        if (isClickable()) {
7579            structure.setClickable(true);
7580        }
7581        if (isFocusable()) {
7582            structure.setFocusable(true);
7583        }
7584        if (isFocused()) {
7585            structure.setFocused(true);
7586        }
7587        if (isAccessibilityFocused()) {
7588            structure.setAccessibilityFocused(true);
7589        }
7590        if (isSelected()) {
7591            structure.setSelected(true);
7592        }
7593        if (isActivated()) {
7594            structure.setActivated(true);
7595        }
7596        if (isLongClickable()) {
7597            structure.setLongClickable(true);
7598        }
7599        if (this instanceof Checkable) {
7600            structure.setCheckable(true);
7601            if (((Checkable)this).isChecked()) {
7602                structure.setChecked(true);
7603            }
7604        }
7605        if (isOpaque()) {
7606            structure.setOpaque(true);
7607        }
7608        if (isContextClickable()) {
7609            structure.setContextClickable(true);
7610        }
7611        structure.setClassName(getAccessibilityClassName().toString());
7612        structure.setContentDescription(getContentDescription());
7613    }
7614
7615    /**
7616     * Called when assist structure is being retrieved from a view as part of
7617     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7618     * generate additional virtual structure under this view.  The defaullt implementation
7619     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7620     * view's virtual accessibility nodes, if any.  You can override this for a more
7621     * optimal implementation providing this data.
7622     */
7623    public void onProvideVirtualStructure(ViewStructure structure) {
7624        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7625        if (provider != null) {
7626            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7627            structure.setChildCount(1);
7628            ViewStructure root = structure.newChild(0);
7629            populateVirtualStructure(root, provider, info);
7630            info.recycle();
7631        }
7632    }
7633
7634    /**
7635     * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
7636     * request.
7637     *
7638     * <p>This method should be used when the view manages a virtual structure under this view. For
7639     * example, a view that draws input fields using {@link #draw(Canvas)}.
7640     *
7641     * <p>When implementing this method, subclasses must follow the rules below:
7642     *
7643     * <ul>
7644     *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
7645     *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
7646     *       identifying the children in the virtual structure.
7647     *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
7648     *       exclude intermediate levels that are irrelevant for autofill; that would improve the
7649     *       autofill performance.
7650     *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7651     *       children.
7652     *   <li>Set the autofill properties of the child structure as defined by
7653     *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
7654     *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
7655     *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
7656     *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7657     *       when the focused virtual child changed.
7658     *   <li>Call
7659     *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
7660     *       when the value of a virtual child changed.
7661     *   <li>Call
7662     *    {@link
7663     *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
7664     *       when the visibility of a virtual child changed.
7665     *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
7666     *       changed and the current context should be committed (for example, when the user tapped
7667     *       a {@code SUBMIT} button in an HTML page).
7668     *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
7669     *       changed and the current context should be canceled (for example, when the user tapped
7670     *       a {@code CANCEL} button in an HTML page).
7671     *   <li>Provide ways for users to manually request autofill by calling
7672     *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
7673     *   <li>The {@code left} and {@code top} values set in
7674     *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
7675     *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
7676     *       structure.
7677     * </ul>
7678     *
7679     * <p>Views with virtual children support the Autofill Framework mainly by:
7680     * <ul>
7681     *   <li>Providing the metadata defining what the virtual children mean and how they can be
7682     *       autofilled.
7683     *   <li>Implementing the methods that autofill the virtual children.
7684     * </ul>
7685     * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
7686     * for the latter.
7687     *
7688     * @param structure fill in with virtual children data for autofill purposes.
7689     * @param flags optional flags.
7690     *
7691     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7692     */
7693    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7694    }
7695
7696    /**
7697     * Automatically fills the content of this view with the {@code value}.
7698     *
7699     * <p>Views support the Autofill Framework mainly by:
7700     * <ul>
7701     *   <li>Providing the metadata defining what the view means and how it can be autofilled.
7702     *   <li>Implementing the methods that autofill the view.
7703     * </ul>
7704     * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
7705     * this method is responsible for latter.
7706     *
7707     * <p>This method does nothing by default, but when overridden it typically:
7708     * <ol>
7709     *   <li>Checks if the provided value matches the expected type (which is defined by
7710     *       {@link #getAutofillType()}).
7711     *   <li>Checks if the view is editable - if it isn't, it should return right away.
7712     *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
7713     *   <li>Pass the actual value to the equivalent setter in the view.
7714     * </ol>
7715     *
7716     * <p>For example, a text-field view could implement the method this way:
7717     *
7718     * <pre class="prettyprint">
7719     * &#64;Override
7720     * public void autofill(AutofillValue value) {
7721     *   if (!value.isText() || !this.isEditable()) {
7722     *      return;
7723     *   }
7724     *   CharSequence text = value.getTextValue();
7725     *   if (text != null) {
7726     *     this.setText(text);
7727     *   }
7728     * }
7729     * </pre>
7730     *
7731     * <p>If the value is updated asynchronously, the next call to
7732     * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
7733     * changed to the autofilled value. If not, the view will not be considered autofilled.
7734     *
7735     * <p><b>Note:</b> After this method is called, the value returned by
7736     * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the
7737     * view will not be highlighted as autofilled.
7738     *
7739     * @param value value to be autofilled.
7740     */
7741    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7742    }
7743
7744    /**
7745     * Automatically fills the content of the virtual children within this view.
7746     *
7747     * <p>Views with virtual children support the Autofill Framework mainly by:
7748     * <ul>
7749     *   <li>Providing the metadata defining what the virtual children mean and how they can be
7750     *       autofilled.
7751     *   <li>Implementing the methods that autofill the virtual children.
7752     * </ul>
7753     * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
7754     * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
7755     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
7756     *
7757     * <p>If a child value is updated asynchronously, the next call to
7758     * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
7759     * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
7760     * considered autofilled.
7761     *
7762     * <p><b>Note:</b> To indicate that a virtual view was autofilled,
7763     * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
7764     * changes.
7765     *
7766     * @param values map of values to be autofilled, keyed by virtual child id.
7767     *
7768     * @attr ref android.R.styleable#Theme_autofilledHighlight
7769     */
7770    public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
7771    }
7772
7773    /**
7774     * Gets the unique identifier of this view in the screen, for autofill purposes.
7775     *
7776     * @return The View's autofill id.
7777     */
7778    public final AutofillId getAutofillId() {
7779        if (mAutofillId == null) {
7780            // The autofill id needs to be unique, but its value doesn't matter,
7781            // so it's better to reuse the accessibility id to save space.
7782            mAutofillId = new AutofillId(getAutofillViewId());
7783        }
7784        return mAutofillId;
7785    }
7786
7787    /**
7788     * Describes the autofill type of this view, so an
7789     * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
7790     * when autofilling the view.
7791     *
7792     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
7793     * support the Autofill Framework.
7794     *
7795     * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
7796     * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
7797     *
7798     * @see #onProvideAutofillStructure(ViewStructure, int)
7799     * @see #autofill(AutofillValue)
7800     */
7801    public @AutofillType int getAutofillType() {
7802        return AUTOFILL_TYPE_NONE;
7803    }
7804
7805    /**
7806     * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
7807     * to autofill the view with the user's data.
7808     *
7809     * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
7810     *
7811     * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
7812     * {@code null} if no hints were set.
7813     *
7814     * @attr ref android.R.styleable#View_autofillHints
7815     */
7816    @ViewDebug.ExportedProperty()
7817    @Nullable public String[] getAutofillHints() {
7818        return mAutofillHints;
7819    }
7820
7821    /**
7822     * @hide
7823     */
7824    public boolean isAutofilled() {
7825        return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
7826    }
7827
7828    /**
7829     * Gets the {@link View}'s current autofill value.
7830     *
7831     * <p>By default returns {@code null}, but subclasses should override it and return an
7832     * appropriate value to properly support the Autofill Framework.
7833     *
7834     * @see #onProvideAutofillStructure(ViewStructure, int)
7835     * @see #autofill(AutofillValue)
7836     */
7837    @Nullable
7838    public AutofillValue getAutofillValue() {
7839        return null;
7840    }
7841
7842    /**
7843     * Gets the mode for determining whether this view is important for autofill.
7844     *
7845     * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
7846     * info about this mode.
7847     *
7848     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7849     * {@link #setImportantForAutofill(int)}.
7850     *
7851     * @attr ref android.R.styleable#View_importantForAutofill
7852     */
7853    @ViewDebug.ExportedProperty(mapping = {
7854            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7855            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7856            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
7857            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
7858                to = "yesExcludeDescendants"),
7859            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
7860                to = "noExcludeDescendants")})
7861    public @AutofillImportance int getImportantForAutofill() {
7862        return (mPrivateFlags3
7863                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7864    }
7865
7866    /**
7867     * Sets the mode for determining whether this view is considered important for autofill.
7868     *
7869     * <p>The platform determines the importance for autofill automatically but you
7870     * can use this method to customize the behavior. For example:
7871     *
7872     * <ol>
7873     *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
7874     *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
7875     *   <li>When both the view and its children are irrelevant for autofill (for example, the root
7876     *       view of an activity containing a spreadhseet editor), it should be
7877     *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7878     *   <li>When the view content is relevant for autofill but its children aren't (for example,
7879     *       a credit card expiration date represented by a custom view that overrides the proper
7880     *       autofill methods and has 2 children representing the month and year), it should
7881     *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
7882     * </ol>
7883     *
7884     * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or
7885     * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
7886     * children) will be always be considered not important; for example, when the user explicitly
7887     * makes an autofill request, all views are considered important. See
7888     * {@link #isImportantForAutofill()} for more details about how the View's importance for
7889     * autofill is used.
7890     *
7891     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7892     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
7893     * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7894     *
7895     * @attr ref android.R.styleable#View_importantForAutofill
7896     */
7897    public void setImportantForAutofill(@AutofillImportance int mode) {
7898        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7899        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7900                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7901    }
7902
7903    /**
7904     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7905     * associated with this view is considered important for autofill purposes.
7906     *
7907     * <p>Generally speaking, a view is important for autofill if:
7908     * <ol>
7909     * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
7910     * <li>The view contents can help an {@link android.service.autofill.AutofillService}
7911     *     determine how other views can be autofilled.
7912     * <ol>
7913     *
7914     * <p>For example, view containers should typically return {@code false} for performance reasons
7915     * (since the important info is provided by their children), but if its properties have relevant
7916     * information (for example, a resource id called {@code credentials}, it should return
7917     * {@code true}. On the other hand, views representing labels or editable fields should
7918     * typically return {@code true}, but in some cases they could return {@code false}
7919     * (for example, if they're part of a "Captcha" mechanism).
7920     *
7921     * <p>The value returned by this method depends on the value returned by
7922     * {@link #getImportantForAutofill()}:
7923     *
7924     * <ol>
7925     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
7926     *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
7927     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
7928     *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
7929     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
7930     *       that can return {@code true} in some cases (like a container with a resource id),
7931     *       but {@code false} in most.
7932     *   <li>otherwise, it returns {@code false}.
7933     * </ol>
7934     *
7935     * <p>When a view is considered important for autofill:
7936     * <ul>
7937     *   <li>The view might automatically trigger an autofill request when focused on.
7938     *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
7939     *       request.
7940     * </ul>
7941     *
7942     * <p>On the other hand, when a view is considered not important for autofill:
7943     * <ul>
7944     *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
7945     *       request through {@link AutofillManager#requestAutofill(View)}.
7946     *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
7947     *       autofill request, unless the request has the
7948     *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
7949     * </ul>
7950     *
7951     * @return whether the view is considered important for autofill.
7952     *
7953     * @see #setImportantForAutofill(int)
7954     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7955     * @see #IMPORTANT_FOR_AUTOFILL_YES
7956     * @see #IMPORTANT_FOR_AUTOFILL_NO
7957     * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7958     * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7959     * @see AutofillManager#requestAutofill(View)
7960     */
7961    public final boolean isImportantForAutofill() {
7962        // Check parent mode to ensure we're not hidden.
7963        ViewParent parent = mParent;
7964        while (parent instanceof View) {
7965            final int parentImportance = ((View) parent).getImportantForAutofill();
7966            if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7967                    || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
7968                return false;
7969            }
7970            parent = parent.getParent();
7971        }
7972
7973        final int importance = getImportantForAutofill();
7974
7975        // First, check the explicit states.
7976        if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7977                || importance == IMPORTANT_FOR_AUTOFILL_YES) {
7978            return true;
7979        }
7980        if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7981                || importance == IMPORTANT_FOR_AUTOFILL_NO) {
7982            return false;
7983        }
7984
7985        // Then use some heuristics to handle AUTO.
7986
7987        // Always include views that have an explicit resource id.
7988        final int id = mID;
7989        if (id != NO_ID && !isViewIdGenerated(id)) {
7990            final Resources res = getResources();
7991            String entry = null;
7992            String pkg = null;
7993            try {
7994                entry = res.getResourceEntryName(id);
7995                pkg = res.getResourcePackageName(id);
7996            } catch (Resources.NotFoundException e) {
7997                // ignore
7998            }
7999            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
8000                return true;
8001            }
8002        }
8003
8004        // Otherwise, assume it's not important...
8005        return false;
8006    }
8007
8008    @Nullable
8009    private AutofillManager getAutofillManager() {
8010        return mContext.getSystemService(AutofillManager.class);
8011    }
8012
8013    private boolean isAutofillable() {
8014        return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill()
8015                && getAutofillViewId() > LAST_APP_AUTOFILL_ID;
8016    }
8017
8018    private void populateVirtualStructure(ViewStructure structure,
8019            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
8020        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
8021                null, null, null);
8022        Rect rect = structure.getTempRect();
8023        info.getBoundsInParent(rect);
8024        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
8025        structure.setVisibility(VISIBLE);
8026        structure.setEnabled(info.isEnabled());
8027        if (info.isClickable()) {
8028            structure.setClickable(true);
8029        }
8030        if (info.isFocusable()) {
8031            structure.setFocusable(true);
8032        }
8033        if (info.isFocused()) {
8034            structure.setFocused(true);
8035        }
8036        if (info.isAccessibilityFocused()) {
8037            structure.setAccessibilityFocused(true);
8038        }
8039        if (info.isSelected()) {
8040            structure.setSelected(true);
8041        }
8042        if (info.isLongClickable()) {
8043            structure.setLongClickable(true);
8044        }
8045        if (info.isCheckable()) {
8046            structure.setCheckable(true);
8047            if (info.isChecked()) {
8048                structure.setChecked(true);
8049            }
8050        }
8051        if (info.isContextClickable()) {
8052            structure.setContextClickable(true);
8053        }
8054        CharSequence cname = info.getClassName();
8055        structure.setClassName(cname != null ? cname.toString() : null);
8056        structure.setContentDescription(info.getContentDescription());
8057        if ((info.getText() != null || info.getError() != null)) {
8058            structure.setText(info.getText(), info.getTextSelectionStart(),
8059                    info.getTextSelectionEnd());
8060        }
8061        final int NCHILDREN = info.getChildCount();
8062        if (NCHILDREN > 0) {
8063            structure.setChildCount(NCHILDREN);
8064            for (int i=0; i<NCHILDREN; i++) {
8065                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
8066                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
8067                ViewStructure child = structure.newChild(i);
8068                populateVirtualStructure(child, provider, cinfo);
8069                cinfo.recycle();
8070            }
8071        }
8072    }
8073
8074    /**
8075     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
8076     * implementation calls {@link #onProvideStructure} and
8077     * {@link #onProvideVirtualStructure}.
8078     */
8079    public void dispatchProvideStructure(ViewStructure structure) {
8080        dispatchProvideStructureForAssistOrAutofill(structure, false, 0);
8081    }
8082
8083    /**
8084     * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
8085     * when an Assist structure is being created as part of an autofill request.
8086     *
8087     * <p>The default implementation does the following:
8088     * <ul>
8089     *   <li>Sets the {@link AutofillId} in the structure.
8090     *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
8091     *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
8092     * </ul>
8093     *
8094     * <p>Typically, this method should only be overridden by subclasses that provide a view
8095     * hierarchy (such as {@link ViewGroup}) - other classes should override
8096     * {@link #onProvideAutofillStructure(ViewStructure, int)} or
8097     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
8098     *
8099     * <p>When overridden, it must:
8100     *
8101     * <ul>
8102     *   <li>Either call
8103     *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
8104     *       set the {@link AutofillId} in the structure (for example, by calling
8105     *       {@code structure.setAutofillId(getAutofillId())}).
8106     *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
8107     *       set, all views in the structure should be considered important for autofill,
8108     *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
8109     *       respect this flag to provide a better user experience - this flag is typically used
8110     *       when an user explicitly requested autofill. If the flag is not set,
8111     *       then only views marked as important for autofill should be included in the
8112     *       structure - skipping non-important views optimizes the overall autofill performance.
8113     * </ul>
8114     *
8115     * @param structure fill in with structured view data for autofill purposes.
8116     * @param flags optional flags.
8117     *
8118     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8119     */
8120    public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
8121            @AutofillFlags int flags) {
8122        dispatchProvideStructureForAssistOrAutofill(structure, true, flags);
8123    }
8124
8125    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
8126            boolean forAutofill, @AutofillFlags int flags) {
8127        if (forAutofill) {
8128            structure.setAutofillId(getAutofillId());
8129            onProvideAutofillStructure(structure, flags);
8130            onProvideAutofillVirtualStructure(structure, flags);
8131        } else if (!isAssistBlocked()) {
8132            onProvideStructure(structure);
8133            onProvideVirtualStructure(structure);
8134        } else {
8135            structure.setClassName(getAccessibilityClassName().toString());
8136            structure.setAssistBlocked(true);
8137        }
8138    }
8139
8140    /**
8141     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
8142     *
8143     * Note: Called from the default {@link AccessibilityDelegate}.
8144     *
8145     * @hide
8146     */
8147    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
8148        if (mAttachInfo == null) {
8149            return;
8150        }
8151
8152        Rect bounds = mAttachInfo.mTmpInvalRect;
8153
8154        getDrawingRect(bounds);
8155        info.setBoundsInParent(bounds);
8156
8157        getBoundsOnScreen(bounds, true);
8158        info.setBoundsInScreen(bounds);
8159
8160        ViewParent parent = getParentForAccessibility();
8161        if (parent instanceof View) {
8162            info.setParent((View) parent);
8163        }
8164
8165        if (mID != View.NO_ID) {
8166            View rootView = getRootView();
8167            if (rootView == null) {
8168                rootView = this;
8169            }
8170
8171            View label = rootView.findLabelForView(this, mID);
8172            if (label != null) {
8173                info.setLabeledBy(label);
8174            }
8175
8176            if ((mAttachInfo.mAccessibilityFetchFlags
8177                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
8178                    && Resources.resourceHasPackage(mID)) {
8179                try {
8180                    String viewId = getResources().getResourceName(mID);
8181                    info.setViewIdResourceName(viewId);
8182                } catch (Resources.NotFoundException nfe) {
8183                    /* ignore */
8184                }
8185            }
8186        }
8187
8188        if (mLabelForId != View.NO_ID) {
8189            View rootView = getRootView();
8190            if (rootView == null) {
8191                rootView = this;
8192            }
8193            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
8194            if (labeled != null) {
8195                info.setLabelFor(labeled);
8196            }
8197        }
8198
8199        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
8200            View rootView = getRootView();
8201            if (rootView == null) {
8202                rootView = this;
8203            }
8204            View next = rootView.findViewInsideOutShouldExist(this,
8205                    mAccessibilityTraversalBeforeId);
8206            if (next != null && next.includeForAccessibility()) {
8207                info.setTraversalBefore(next);
8208            }
8209        }
8210
8211        if (mAccessibilityTraversalAfterId != View.NO_ID) {
8212            View rootView = getRootView();
8213            if (rootView == null) {
8214                rootView = this;
8215            }
8216            View next = rootView.findViewInsideOutShouldExist(this,
8217                    mAccessibilityTraversalAfterId);
8218            if (next != null && next.includeForAccessibility()) {
8219                info.setTraversalAfter(next);
8220            }
8221        }
8222
8223        info.setVisibleToUser(isVisibleToUser());
8224
8225        info.setImportantForAccessibility(isImportantForAccessibility());
8226        info.setPackageName(mContext.getPackageName());
8227        info.setClassName(getAccessibilityClassName());
8228        info.setContentDescription(getContentDescription());
8229
8230        info.setEnabled(isEnabled());
8231        info.setClickable(isClickable());
8232        info.setFocusable(isFocusable());
8233        info.setFocused(isFocused());
8234        info.setAccessibilityFocused(isAccessibilityFocused());
8235        info.setSelected(isSelected());
8236        info.setLongClickable(isLongClickable());
8237        info.setContextClickable(isContextClickable());
8238        info.setLiveRegion(getAccessibilityLiveRegion());
8239
8240        // TODO: These make sense only if we are in an AdapterView but all
8241        // views can be selected. Maybe from accessibility perspective
8242        // we should report as selectable view in an AdapterView.
8243        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
8244        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
8245
8246        if (isFocusable()) {
8247            if (isFocused()) {
8248                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
8249            } else {
8250                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
8251            }
8252        }
8253
8254        if (!isAccessibilityFocused()) {
8255            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
8256        } else {
8257            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
8258        }
8259
8260        if (isClickable() && isEnabled()) {
8261            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
8262        }
8263
8264        if (isLongClickable() && isEnabled()) {
8265            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
8266        }
8267
8268        if (isContextClickable() && isEnabled()) {
8269            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
8270        }
8271
8272        CharSequence text = getIterableTextForAccessibility();
8273        if (text != null && text.length() > 0) {
8274            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
8275
8276            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
8277            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
8278            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
8279            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
8280                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
8281                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
8282        }
8283
8284        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
8285        populateAccessibilityNodeInfoDrawingOrderInParent(info);
8286    }
8287
8288    /**
8289     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
8290     * additional data.
8291     * <p>
8292     * This method only needs overloading if the node is marked as having extra data available.
8293     * </p>
8294     *
8295     * @param info The info to which to add the extra data. Never {@code null}.
8296     * @param extraDataKey A key specifying the type of extra data to add to the info. The
8297     *                     extra data should be added to the {@link Bundle} returned by
8298     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
8299     *                     {@code null}.
8300     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
8301     *                  {@code null} if the service provided no arguments.
8302     *
8303     * @see AccessibilityNodeInfo#setAvailableExtraData(List)
8304     */
8305    public void addExtraDataToAccessibilityNodeInfo(
8306            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
8307            @Nullable Bundle arguments) {
8308    }
8309
8310    /**
8311     * Determine the order in which this view will be drawn relative to its siblings for a11y
8312     *
8313     * @param info The info whose drawing order should be populated
8314     */
8315    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
8316        /*
8317         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
8318         * drawing order may not be well-defined, and some Views with custom drawing order may
8319         * not be initialized sufficiently to respond properly getChildDrawingOrder.
8320         */
8321        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
8322            info.setDrawingOrder(0);
8323            return;
8324        }
8325        int drawingOrderInParent = 1;
8326        // Iterate up the hierarchy if parents are not important for a11y
8327        View viewAtDrawingLevel = this;
8328        final ViewParent parent = getParentForAccessibility();
8329        while (viewAtDrawingLevel != parent) {
8330            final ViewParent currentParent = viewAtDrawingLevel.getParent();
8331            if (!(currentParent instanceof ViewGroup)) {
8332                // Should only happen for the Decor
8333                drawingOrderInParent = 0;
8334                break;
8335            } else {
8336                final ViewGroup parentGroup = (ViewGroup) currentParent;
8337                final int childCount = parentGroup.getChildCount();
8338                if (childCount > 1) {
8339                    List<View> preorderedList = parentGroup.buildOrderedChildList();
8340                    if (preorderedList != null) {
8341                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
8342                        for (int i = 0; i < childDrawIndex; i++) {
8343                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
8344                        }
8345                    } else {
8346                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
8347                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
8348                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
8349                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
8350                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
8351                        if (childDrawIndex != 0) {
8352                            for (int i = 0; i < numChildrenToIterate; i++) {
8353                                final int otherDrawIndex = (customOrder ?
8354                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
8355                                if (otherDrawIndex < childDrawIndex) {
8356                                    drawingOrderInParent +=
8357                                            numViewsForAccessibility(parentGroup.getChildAt(i));
8358                                }
8359                            }
8360                        }
8361                    }
8362                }
8363            }
8364            viewAtDrawingLevel = (View) currentParent;
8365        }
8366        info.setDrawingOrder(drawingOrderInParent);
8367    }
8368
8369    private static int numViewsForAccessibility(View view) {
8370        if (view != null) {
8371            if (view.includeForAccessibility()) {
8372                return 1;
8373            } else if (view instanceof ViewGroup) {
8374                return ((ViewGroup) view).getNumChildrenForAccessibility();
8375            }
8376        }
8377        return 0;
8378    }
8379
8380    private View findLabelForView(View view, int labeledId) {
8381        if (mMatchLabelForPredicate == null) {
8382            mMatchLabelForPredicate = new MatchLabelForPredicate();
8383        }
8384        mMatchLabelForPredicate.mLabeledId = labeledId;
8385        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
8386    }
8387
8388    /**
8389     * Computes whether this view is visible to the user. Such a view is
8390     * attached, visible, all its predecessors are visible, it is not clipped
8391     * entirely by its predecessors, and has an alpha greater than zero.
8392     *
8393     * @return Whether the view is visible on the screen.
8394     *
8395     * @hide
8396     */
8397    protected boolean isVisibleToUser() {
8398        return isVisibleToUser(null);
8399    }
8400
8401    /**
8402     * Computes whether the given portion of this view is visible to the user.
8403     * Such a view is attached, visible, all its predecessors are visible,
8404     * has an alpha greater than zero, and the specified portion is not
8405     * clipped entirely by its predecessors.
8406     *
8407     * @param boundInView the portion of the view to test; coordinates should be relative; may be
8408     *                    <code>null</code>, and the entire view will be tested in this case.
8409     *                    When <code>true</code> is returned by the function, the actual visible
8410     *                    region will be stored in this parameter; that is, if boundInView is fully
8411     *                    contained within the view, no modification will be made, otherwise regions
8412     *                    outside of the visible area of the view will be clipped.
8413     *
8414     * @return Whether the specified portion of the view is visible on the screen.
8415     *
8416     * @hide
8417     */
8418    protected boolean isVisibleToUser(Rect boundInView) {
8419        if (mAttachInfo != null) {
8420            // Attached to invisible window means this view is not visible.
8421            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8422                return false;
8423            }
8424            // An invisible predecessor or one with alpha zero means
8425            // that this view is not visible to the user.
8426            Object current = this;
8427            while (current instanceof View) {
8428                View view = (View) current;
8429                // We have attach info so this view is attached and there is no
8430                // need to check whether we reach to ViewRootImpl on the way up.
8431                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8432                        view.getVisibility() != VISIBLE) {
8433                    return false;
8434                }
8435                current = view.mParent;
8436            }
8437            // Check if the view is entirely covered by its predecessors.
8438            Rect visibleRect = mAttachInfo.mTmpInvalRect;
8439            Point offset = mAttachInfo.mPoint;
8440            if (!getGlobalVisibleRect(visibleRect, offset)) {
8441                return false;
8442            }
8443            // Check if the visible portion intersects the rectangle of interest.
8444            if (boundInView != null) {
8445                visibleRect.offset(-offset.x, -offset.y);
8446                return boundInView.intersect(visibleRect);
8447            }
8448            return true;
8449        }
8450        return false;
8451    }
8452
8453    /**
8454     * Returns the delegate for implementing accessibility support via
8455     * composition. For more details see {@link AccessibilityDelegate}.
8456     *
8457     * @return The delegate, or null if none set.
8458     *
8459     * @hide
8460     */
8461    public AccessibilityDelegate getAccessibilityDelegate() {
8462        return mAccessibilityDelegate;
8463    }
8464
8465    /**
8466     * Sets a delegate for implementing accessibility support via composition
8467     * (as opposed to inheritance). For more details, see
8468     * {@link AccessibilityDelegate}.
8469     * <p>
8470     * <strong>Note:</strong> On platform versions prior to
8471     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8472     * views in the {@code android.widget.*} package are called <i>before</i>
8473     * host methods. This prevents certain properties such as class name from
8474     * being modified by overriding
8475     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8476     * as any changes will be overwritten by the host class.
8477     * <p>
8478     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8479     * methods are called <i>after</i> host methods, which all properties to be
8480     * modified without being overwritten by the host class.
8481     *
8482     * @param delegate the object to which accessibility method calls should be
8483     *                 delegated
8484     * @see AccessibilityDelegate
8485     */
8486    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8487        mAccessibilityDelegate = delegate;
8488    }
8489
8490    /**
8491     * Gets the provider for managing a virtual view hierarchy rooted at this View
8492     * and reported to {@link android.accessibilityservice.AccessibilityService}s
8493     * that explore the window content.
8494     * <p>
8495     * If this method returns an instance, this instance is responsible for managing
8496     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8497     * View including the one representing the View itself. Similarly the returned
8498     * instance is responsible for performing accessibility actions on any virtual
8499     * view or the root view itself.
8500     * </p>
8501     * <p>
8502     * If an {@link AccessibilityDelegate} has been specified via calling
8503     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8504     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8505     * is responsible for handling this call.
8506     * </p>
8507     *
8508     * @return The provider.
8509     *
8510     * @see AccessibilityNodeProvider
8511     */
8512    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8513        if (mAccessibilityDelegate != null) {
8514            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8515        } else {
8516            return null;
8517        }
8518    }
8519
8520    /**
8521     * Gets the unique identifier of this view on the screen for accessibility purposes.
8522     *
8523     * @return The view accessibility id.
8524     *
8525     * @hide
8526     */
8527    public int getAccessibilityViewId() {
8528        if (mAccessibilityViewId == NO_ID) {
8529            mAccessibilityViewId = sNextAccessibilityViewId++;
8530        }
8531        return mAccessibilityViewId;
8532    }
8533
8534    /**
8535     * Gets the unique identifier of this view on the screen for autofill purposes.
8536     *
8537     * @return The view autofill id.
8538     *
8539     * @hide
8540     */
8541    public int getAutofillViewId() {
8542        if (mAutofillViewId == NO_ID) {
8543            mAutofillViewId = mContext.getNextAutofillId();
8544        }
8545        return mAutofillViewId;
8546    }
8547
8548    /**
8549     * Gets the unique identifier of the window in which this View reseides.
8550     *
8551     * @return The window accessibility id.
8552     *
8553     * @hide
8554     */
8555    public int getAccessibilityWindowId() {
8556        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8557                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8558    }
8559
8560    /**
8561     * Returns the {@link View}'s content description.
8562     * <p>
8563     * <strong>Note:</strong> Do not override this method, as it will have no
8564     * effect on the content description presented to accessibility services.
8565     * You must call {@link #setContentDescription(CharSequence)} to modify the
8566     * content description.
8567     *
8568     * @return the content description
8569     * @see #setContentDescription(CharSequence)
8570     * @attr ref android.R.styleable#View_contentDescription
8571     */
8572    @ViewDebug.ExportedProperty(category = "accessibility")
8573    public CharSequence getContentDescription() {
8574        return mContentDescription;
8575    }
8576
8577    /**
8578     * Sets the {@link View}'s content description.
8579     * <p>
8580     * A content description briefly describes the view and is primarily used
8581     * for accessibility support to determine how a view should be presented to
8582     * the user. In the case of a view with no textual representation, such as
8583     * {@link android.widget.ImageButton}, a useful content description
8584     * explains what the view does. For example, an image button with a phone
8585     * icon that is used to place a call may use "Call" as its content
8586     * description. An image of a floppy disk that is used to save a file may
8587     * use "Save".
8588     *
8589     * @param contentDescription The content description.
8590     * @see #getContentDescription()
8591     * @attr ref android.R.styleable#View_contentDescription
8592     */
8593    @RemotableViewMethod
8594    public void setContentDescription(CharSequence contentDescription) {
8595        if (mContentDescription == null) {
8596            if (contentDescription == null) {
8597                return;
8598            }
8599        } else if (mContentDescription.equals(contentDescription)) {
8600            return;
8601        }
8602        mContentDescription = contentDescription;
8603        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8604        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8605            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8606            notifySubtreeAccessibilityStateChangedIfNeeded();
8607        } else {
8608            notifyViewAccessibilityStateChangedIfNeeded(
8609                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8610        }
8611    }
8612
8613    /**
8614     * Sets the id of a view before which this one is visited in accessibility traversal.
8615     * A screen-reader must visit the content of this view before the content of the one
8616     * it precedes. For example, if view B is set to be before view A, then a screen-reader
8617     * will traverse the entire content of B before traversing the entire content of A,
8618     * regardles of what traversal strategy it is using.
8619     * <p>
8620     * Views that do not have specified before/after relationships are traversed in order
8621     * determined by the screen-reader.
8622     * </p>
8623     * <p>
8624     * Setting that this view is before a view that is not important for accessibility
8625     * or if this view is not important for accessibility will have no effect as the
8626     * screen-reader is not aware of unimportant views.
8627     * </p>
8628     *
8629     * @param beforeId The id of a view this one precedes in accessibility traversal.
8630     *
8631     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8632     *
8633     * @see #setImportantForAccessibility(int)
8634     */
8635    @RemotableViewMethod
8636    public void setAccessibilityTraversalBefore(int beforeId) {
8637        if (mAccessibilityTraversalBeforeId == beforeId) {
8638            return;
8639        }
8640        mAccessibilityTraversalBeforeId = beforeId;
8641        notifyViewAccessibilityStateChangedIfNeeded(
8642                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8643    }
8644
8645    /**
8646     * Gets the id of a view before which this one is visited in accessibility traversal.
8647     *
8648     * @return The id of a view this one precedes in accessibility traversal if
8649     *         specified, otherwise {@link #NO_ID}.
8650     *
8651     * @see #setAccessibilityTraversalBefore(int)
8652     */
8653    public int getAccessibilityTraversalBefore() {
8654        return mAccessibilityTraversalBeforeId;
8655    }
8656
8657    /**
8658     * Sets the id of a view after which this one is visited in accessibility traversal.
8659     * A screen-reader must visit the content of the other view before the content of this
8660     * one. For example, if view B is set to be after view A, then a screen-reader
8661     * will traverse the entire content of A before traversing the entire content of B,
8662     * regardles of what traversal strategy it is using.
8663     * <p>
8664     * Views that do not have specified before/after relationships are traversed in order
8665     * determined by the screen-reader.
8666     * </p>
8667     * <p>
8668     * Setting that this view is after a view that is not important for accessibility
8669     * or if this view is not important for accessibility will have no effect as the
8670     * screen-reader is not aware of unimportant views.
8671     * </p>
8672     *
8673     * @param afterId The id of a view this one succedees in accessibility traversal.
8674     *
8675     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8676     *
8677     * @see #setImportantForAccessibility(int)
8678     */
8679    @RemotableViewMethod
8680    public void setAccessibilityTraversalAfter(int afterId) {
8681        if (mAccessibilityTraversalAfterId == afterId) {
8682            return;
8683        }
8684        mAccessibilityTraversalAfterId = afterId;
8685        notifyViewAccessibilityStateChangedIfNeeded(
8686                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8687    }
8688
8689    /**
8690     * Gets the id of a view after which this one is visited in accessibility traversal.
8691     *
8692     * @return The id of a view this one succeedes in accessibility traversal if
8693     *         specified, otherwise {@link #NO_ID}.
8694     *
8695     * @see #setAccessibilityTraversalAfter(int)
8696     */
8697    public int getAccessibilityTraversalAfter() {
8698        return mAccessibilityTraversalAfterId;
8699    }
8700
8701    /**
8702     * Gets the id of a view for which this view serves as a label for
8703     * accessibility purposes.
8704     *
8705     * @return The labeled view id.
8706     */
8707    @ViewDebug.ExportedProperty(category = "accessibility")
8708    public int getLabelFor() {
8709        return mLabelForId;
8710    }
8711
8712    /**
8713     * Sets the id of a view for which this view serves as a label for
8714     * accessibility purposes.
8715     *
8716     * @param id The labeled view id.
8717     */
8718    @RemotableViewMethod
8719    public void setLabelFor(@IdRes int id) {
8720        if (mLabelForId == id) {
8721            return;
8722        }
8723        mLabelForId = id;
8724        if (mLabelForId != View.NO_ID
8725                && mID == View.NO_ID) {
8726            mID = generateViewId();
8727        }
8728        notifyViewAccessibilityStateChangedIfNeeded(
8729                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8730    }
8731
8732    /**
8733     * Invoked whenever this view loses focus, either by losing window focus or by losing
8734     * focus within its window. This method can be used to clear any state tied to the
8735     * focus. For instance, if a button is held pressed with the trackball and the window
8736     * loses focus, this method can be used to cancel the press.
8737     *
8738     * Subclasses of View overriding this method should always call super.onFocusLost().
8739     *
8740     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8741     * @see #onWindowFocusChanged(boolean)
8742     *
8743     * @hide pending API council approval
8744     */
8745    @CallSuper
8746    protected void onFocusLost() {
8747        resetPressedState();
8748    }
8749
8750    private void resetPressedState() {
8751        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8752            return;
8753        }
8754
8755        if (isPressed()) {
8756            setPressed(false);
8757
8758            if (!mHasPerformedLongPress) {
8759                removeLongPressCallback();
8760            }
8761        }
8762    }
8763
8764    /**
8765     * Returns true if this view has focus
8766     *
8767     * @return True if this view has focus, false otherwise.
8768     */
8769    @ViewDebug.ExportedProperty(category = "focus")
8770    public boolean isFocused() {
8771        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8772    }
8773
8774    /**
8775     * Find the view in the hierarchy rooted at this view that currently has
8776     * focus.
8777     *
8778     * @return The view that currently has focus, or null if no focused view can
8779     *         be found.
8780     */
8781    public View findFocus() {
8782        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8783    }
8784
8785    /**
8786     * Indicates whether this view is one of the set of scrollable containers in
8787     * its window.
8788     *
8789     * @return whether this view is one of the set of scrollable containers in
8790     * its window
8791     *
8792     * @attr ref android.R.styleable#View_isScrollContainer
8793     */
8794    public boolean isScrollContainer() {
8795        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8796    }
8797
8798    /**
8799     * Change whether this view is one of the set of scrollable containers in
8800     * its window.  This will be used to determine whether the window can
8801     * resize or must pan when a soft input area is open -- scrollable
8802     * containers allow the window to use resize mode since the container
8803     * will appropriately shrink.
8804     *
8805     * @attr ref android.R.styleable#View_isScrollContainer
8806     */
8807    public void setScrollContainer(boolean isScrollContainer) {
8808        if (isScrollContainer) {
8809            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8810                mAttachInfo.mScrollContainers.add(this);
8811                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8812            }
8813            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8814        } else {
8815            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8816                mAttachInfo.mScrollContainers.remove(this);
8817            }
8818            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8819        }
8820    }
8821
8822    /**
8823     * Returns the quality of the drawing cache.
8824     *
8825     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8826     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8827     *
8828     * @see #setDrawingCacheQuality(int)
8829     * @see #setDrawingCacheEnabled(boolean)
8830     * @see #isDrawingCacheEnabled()
8831     *
8832     * @attr ref android.R.styleable#View_drawingCacheQuality
8833     */
8834    @DrawingCacheQuality
8835    public int getDrawingCacheQuality() {
8836        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8837    }
8838
8839    /**
8840     * Set the drawing cache quality of this view. This value is used only when the
8841     * drawing cache is enabled
8842     *
8843     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8844     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8845     *
8846     * @see #getDrawingCacheQuality()
8847     * @see #setDrawingCacheEnabled(boolean)
8848     * @see #isDrawingCacheEnabled()
8849     *
8850     * @attr ref android.R.styleable#View_drawingCacheQuality
8851     */
8852    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8853        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8854    }
8855
8856    /**
8857     * Returns whether the screen should remain on, corresponding to the current
8858     * value of {@link #KEEP_SCREEN_ON}.
8859     *
8860     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8861     *
8862     * @see #setKeepScreenOn(boolean)
8863     *
8864     * @attr ref android.R.styleable#View_keepScreenOn
8865     */
8866    public boolean getKeepScreenOn() {
8867        return (mViewFlags & KEEP_SCREEN_ON) != 0;
8868    }
8869
8870    /**
8871     * Controls whether the screen should remain on, modifying the
8872     * value of {@link #KEEP_SCREEN_ON}.
8873     *
8874     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8875     *
8876     * @see #getKeepScreenOn()
8877     *
8878     * @attr ref android.R.styleable#View_keepScreenOn
8879     */
8880    public void setKeepScreenOn(boolean keepScreenOn) {
8881        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8882    }
8883
8884    /**
8885     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8886     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8887     *
8888     * @attr ref android.R.styleable#View_nextFocusLeft
8889     */
8890    public int getNextFocusLeftId() {
8891        return mNextFocusLeftId;
8892    }
8893
8894    /**
8895     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8896     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8897     * decide automatically.
8898     *
8899     * @attr ref android.R.styleable#View_nextFocusLeft
8900     */
8901    public void setNextFocusLeftId(int nextFocusLeftId) {
8902        mNextFocusLeftId = nextFocusLeftId;
8903    }
8904
8905    /**
8906     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8907     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8908     *
8909     * @attr ref android.R.styleable#View_nextFocusRight
8910     */
8911    public int getNextFocusRightId() {
8912        return mNextFocusRightId;
8913    }
8914
8915    /**
8916     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8917     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8918     * decide automatically.
8919     *
8920     * @attr ref android.R.styleable#View_nextFocusRight
8921     */
8922    public void setNextFocusRightId(int nextFocusRightId) {
8923        mNextFocusRightId = nextFocusRightId;
8924    }
8925
8926    /**
8927     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8928     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8929     *
8930     * @attr ref android.R.styleable#View_nextFocusUp
8931     */
8932    public int getNextFocusUpId() {
8933        return mNextFocusUpId;
8934    }
8935
8936    /**
8937     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8938     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8939     * decide automatically.
8940     *
8941     * @attr ref android.R.styleable#View_nextFocusUp
8942     */
8943    public void setNextFocusUpId(int nextFocusUpId) {
8944        mNextFocusUpId = nextFocusUpId;
8945    }
8946
8947    /**
8948     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8949     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8950     *
8951     * @attr ref android.R.styleable#View_nextFocusDown
8952     */
8953    public int getNextFocusDownId() {
8954        return mNextFocusDownId;
8955    }
8956
8957    /**
8958     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8959     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8960     * decide automatically.
8961     *
8962     * @attr ref android.R.styleable#View_nextFocusDown
8963     */
8964    public void setNextFocusDownId(int nextFocusDownId) {
8965        mNextFocusDownId = nextFocusDownId;
8966    }
8967
8968    /**
8969     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8970     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8971     *
8972     * @attr ref android.R.styleable#View_nextFocusForward
8973     */
8974    public int getNextFocusForwardId() {
8975        return mNextFocusForwardId;
8976    }
8977
8978    /**
8979     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8980     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8981     * decide automatically.
8982     *
8983     * @attr ref android.R.styleable#View_nextFocusForward
8984     */
8985    public void setNextFocusForwardId(int nextFocusForwardId) {
8986        mNextFocusForwardId = nextFocusForwardId;
8987    }
8988
8989    /**
8990     * Gets the id of the root of the next keyboard navigation cluster.
8991     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8992     * decide automatically.
8993     *
8994     * @attr ref android.R.styleable#View_nextClusterForward
8995     */
8996    public int getNextClusterForwardId() {
8997        return mNextClusterForwardId;
8998    }
8999
9000    /**
9001     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
9002     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
9003     * decide automatically.
9004     *
9005     * @attr ref android.R.styleable#View_nextClusterForward
9006     */
9007    public void setNextClusterForwardId(int nextClusterForwardId) {
9008        mNextClusterForwardId = nextClusterForwardId;
9009    }
9010
9011    /**
9012     * Returns the visibility of this view and all of its ancestors
9013     *
9014     * @return True if this view and all of its ancestors are {@link #VISIBLE}
9015     */
9016    public boolean isShown() {
9017        View current = this;
9018        //noinspection ConstantConditions
9019        do {
9020            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
9021                return false;
9022            }
9023            ViewParent parent = current.mParent;
9024            if (parent == null) {
9025                return false; // We are not attached to the view root
9026            }
9027            if (!(parent instanceof View)) {
9028                return true;
9029            }
9030            current = (View) parent;
9031        } while (current != null);
9032
9033        return false;
9034    }
9035
9036    /**
9037     * Called by the view hierarchy when the content insets for a window have
9038     * changed, to allow it to adjust its content to fit within those windows.
9039     * The content insets tell you the space that the status bar, input method,
9040     * and other system windows infringe on the application's window.
9041     *
9042     * <p>You do not normally need to deal with this function, since the default
9043     * window decoration given to applications takes care of applying it to the
9044     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
9045     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
9046     * and your content can be placed under those system elements.  You can then
9047     * use this method within your view hierarchy if you have parts of your UI
9048     * which you would like to ensure are not being covered.
9049     *
9050     * <p>The default implementation of this method simply applies the content
9051     * insets to the view's padding, consuming that content (modifying the
9052     * insets to be 0), and returning true.  This behavior is off by default, but can
9053     * be enabled through {@link #setFitsSystemWindows(boolean)}.
9054     *
9055     * <p>This function's traversal down the hierarchy is depth-first.  The same content
9056     * insets object is propagated down the hierarchy, so any changes made to it will
9057     * be seen by all following views (including potentially ones above in
9058     * the hierarchy since this is a depth-first traversal).  The first view
9059     * that returns true will abort the entire traversal.
9060     *
9061     * <p>The default implementation works well for a situation where it is
9062     * used with a container that covers the entire window, allowing it to
9063     * apply the appropriate insets to its content on all edges.  If you need
9064     * a more complicated layout (such as two different views fitting system
9065     * windows, one on the top of the window, and one on the bottom),
9066     * you can override the method and handle the insets however you would like.
9067     * Note that the insets provided by the framework are always relative to the
9068     * far edges of the window, not accounting for the location of the called view
9069     * within that window.  (In fact when this method is called you do not yet know
9070     * where the layout will place the view, as it is done before layout happens.)
9071     *
9072     * <p>Note: unlike many View methods, there is no dispatch phase to this
9073     * call.  If you are overriding it in a ViewGroup and want to allow the
9074     * call to continue to your children, you must be sure to call the super
9075     * implementation.
9076     *
9077     * <p>Here is a sample layout that makes use of fitting system windows
9078     * to have controls for a video view placed inside of the window decorations
9079     * that it hides and shows.  This can be used with code like the second
9080     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
9081     *
9082     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
9083     *
9084     * @param insets Current content insets of the window.  Prior to
9085     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
9086     * the insets or else you and Android will be unhappy.
9087     *
9088     * @return {@code true} if this view applied the insets and it should not
9089     * continue propagating further down the hierarchy, {@code false} otherwise.
9090     * @see #getFitsSystemWindows()
9091     * @see #setFitsSystemWindows(boolean)
9092     * @see #setSystemUiVisibility(int)
9093     *
9094     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
9095     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
9096     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
9097     * to implement handling their own insets.
9098     */
9099    @Deprecated
9100    protected boolean fitSystemWindows(Rect insets) {
9101        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
9102            if (insets == null) {
9103                // Null insets by definition have already been consumed.
9104                // This call cannot apply insets since there are none to apply,
9105                // so return false.
9106                return false;
9107            }
9108            // If we're not in the process of dispatching the newer apply insets call,
9109            // that means we're not in the compatibility path. Dispatch into the newer
9110            // apply insets path and take things from there.
9111            try {
9112                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
9113                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
9114            } finally {
9115                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
9116            }
9117        } else {
9118            // We're being called from the newer apply insets path.
9119            // Perform the standard fallback behavior.
9120            return fitSystemWindowsInt(insets);
9121        }
9122    }
9123
9124    private boolean fitSystemWindowsInt(Rect insets) {
9125        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
9126            mUserPaddingStart = UNDEFINED_PADDING;
9127            mUserPaddingEnd = UNDEFINED_PADDING;
9128            Rect localInsets = sThreadLocal.get();
9129            if (localInsets == null) {
9130                localInsets = new Rect();
9131                sThreadLocal.set(localInsets);
9132            }
9133            boolean res = computeFitSystemWindows(insets, localInsets);
9134            mUserPaddingLeftInitial = localInsets.left;
9135            mUserPaddingRightInitial = localInsets.right;
9136            internalSetPadding(localInsets.left, localInsets.top,
9137                    localInsets.right, localInsets.bottom);
9138            return res;
9139        }
9140        return false;
9141    }
9142
9143    /**
9144     * Called when the view should apply {@link WindowInsets} according to its internal policy.
9145     *
9146     * <p>This method should be overridden by views that wish to apply a policy different from or
9147     * in addition to the default behavior. Clients that wish to force a view subtree
9148     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
9149     *
9150     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
9151     * it will be called during dispatch instead of this method. The listener may optionally
9152     * call this method from its own implementation if it wishes to apply the view's default
9153     * insets policy in addition to its own.</p>
9154     *
9155     * <p>Implementations of this method should either return the insets parameter unchanged
9156     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
9157     * that this view applied itself. This allows new inset types added in future platform
9158     * versions to pass through existing implementations unchanged without being erroneously
9159     * consumed.</p>
9160     *
9161     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
9162     * property is set then the view will consume the system window insets and apply them
9163     * as padding for the view.</p>
9164     *
9165     * @param insets Insets to apply
9166     * @return The supplied insets with any applied insets consumed
9167     */
9168    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
9169        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
9170            // We weren't called from within a direct call to fitSystemWindows,
9171            // call into it as a fallback in case we're in a class that overrides it
9172            // and has logic to perform.
9173            if (fitSystemWindows(insets.getSystemWindowInsets())) {
9174                return insets.consumeSystemWindowInsets();
9175            }
9176        } else {
9177            // We were called from within a direct call to fitSystemWindows.
9178            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
9179                return insets.consumeSystemWindowInsets();
9180            }
9181        }
9182        return insets;
9183    }
9184
9185    /**
9186     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
9187     * window insets to this view. The listener's
9188     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
9189     * method will be called instead of the view's
9190     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
9191     *
9192     * @param listener Listener to set
9193     *
9194     * @see #onApplyWindowInsets(WindowInsets)
9195     */
9196    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
9197        getListenerInfo().mOnApplyWindowInsetsListener = listener;
9198    }
9199
9200    /**
9201     * Request to apply the given window insets to this view or another view in its subtree.
9202     *
9203     * <p>This method should be called by clients wishing to apply insets corresponding to areas
9204     * obscured by window decorations or overlays. This can include the status and navigation bars,
9205     * action bars, input methods and more. New inset categories may be added in the future.
9206     * The method returns the insets provided minus any that were applied by this view or its
9207     * children.</p>
9208     *
9209     * <p>Clients wishing to provide custom behavior should override the
9210     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
9211     * {@link OnApplyWindowInsetsListener} via the
9212     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
9213     * method.</p>
9214     *
9215     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
9216     * </p>
9217     *
9218     * @param insets Insets to apply
9219     * @return The provided insets minus the insets that were consumed
9220     */
9221    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
9222        try {
9223            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
9224            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
9225                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
9226            } else {
9227                return onApplyWindowInsets(insets);
9228            }
9229        } finally {
9230            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
9231        }
9232    }
9233
9234    /**
9235     * Compute the view's coordinate within the surface.
9236     *
9237     * <p>Computes the coordinates of this view in its surface. The argument
9238     * must be an array of two integers. After the method returns, the array
9239     * contains the x and y location in that order.</p>
9240     * @hide
9241     * @param location an array of two integers in which to hold the coordinates
9242     */
9243    public void getLocationInSurface(@Size(2) int[] location) {
9244        getLocationInWindow(location);
9245        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
9246            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
9247            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
9248        }
9249    }
9250
9251    /**
9252     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
9253     * only available if the view is attached.
9254     *
9255     * @return WindowInsets from the top of the view hierarchy or null if View is detached
9256     */
9257    public WindowInsets getRootWindowInsets() {
9258        if (mAttachInfo != null) {
9259            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
9260        }
9261        return null;
9262    }
9263
9264    /**
9265     * @hide Compute the insets that should be consumed by this view and the ones
9266     * that should propagate to those under it.
9267     */
9268    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
9269        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9270                || mAttachInfo == null
9271                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
9272                        && !mAttachInfo.mOverscanRequested)) {
9273            outLocalInsets.set(inoutInsets);
9274            inoutInsets.set(0, 0, 0, 0);
9275            return true;
9276        } else {
9277            // The application wants to take care of fitting system window for
9278            // the content...  however we still need to take care of any overscan here.
9279            final Rect overscan = mAttachInfo.mOverscanInsets;
9280            outLocalInsets.set(overscan);
9281            inoutInsets.left -= overscan.left;
9282            inoutInsets.top -= overscan.top;
9283            inoutInsets.right -= overscan.right;
9284            inoutInsets.bottom -= overscan.bottom;
9285            return false;
9286        }
9287    }
9288
9289    /**
9290     * Compute insets that should be consumed by this view and the ones that should propagate
9291     * to those under it.
9292     *
9293     * @param in Insets currently being processed by this View, likely received as a parameter
9294     *           to {@link #onApplyWindowInsets(WindowInsets)}.
9295     * @param outLocalInsets A Rect that will receive the insets that should be consumed
9296     *                       by this view
9297     * @return Insets that should be passed along to views under this one
9298     */
9299    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
9300        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9301                || mAttachInfo == null
9302                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
9303            outLocalInsets.set(in.getSystemWindowInsets());
9304            return in.consumeSystemWindowInsets();
9305        } else {
9306            outLocalInsets.set(0, 0, 0, 0);
9307            return in;
9308        }
9309    }
9310
9311    /**
9312     * Sets whether or not this view should account for system screen decorations
9313     * such as the status bar and inset its content; that is, controlling whether
9314     * the default implementation of {@link #fitSystemWindows(Rect)} will be
9315     * executed.  See that method for more details.
9316     *
9317     * <p>Note that if you are providing your own implementation of
9318     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
9319     * flag to true -- your implementation will be overriding the default
9320     * implementation that checks this flag.
9321     *
9322     * @param fitSystemWindows If true, then the default implementation of
9323     * {@link #fitSystemWindows(Rect)} will be executed.
9324     *
9325     * @attr ref android.R.styleable#View_fitsSystemWindows
9326     * @see #getFitsSystemWindows()
9327     * @see #fitSystemWindows(Rect)
9328     * @see #setSystemUiVisibility(int)
9329     */
9330    public void setFitsSystemWindows(boolean fitSystemWindows) {
9331        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
9332    }
9333
9334    /**
9335     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
9336     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
9337     * will be executed.
9338     *
9339     * @return {@code true} if the default implementation of
9340     * {@link #fitSystemWindows(Rect)} will be executed.
9341     *
9342     * @attr ref android.R.styleable#View_fitsSystemWindows
9343     * @see #setFitsSystemWindows(boolean)
9344     * @see #fitSystemWindows(Rect)
9345     * @see #setSystemUiVisibility(int)
9346     */
9347    @ViewDebug.ExportedProperty
9348    public boolean getFitsSystemWindows() {
9349        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
9350    }
9351
9352    /** @hide */
9353    public boolean fitsSystemWindows() {
9354        return getFitsSystemWindows();
9355    }
9356
9357    /**
9358     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
9359     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
9360     */
9361    @Deprecated
9362    public void requestFitSystemWindows() {
9363        if (mParent != null) {
9364            mParent.requestFitSystemWindows();
9365        }
9366    }
9367
9368    /**
9369     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
9370     */
9371    public void requestApplyInsets() {
9372        requestFitSystemWindows();
9373    }
9374
9375    /**
9376     * For use by PhoneWindow to make its own system window fitting optional.
9377     * @hide
9378     */
9379    public void makeOptionalFitsSystemWindows() {
9380        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
9381    }
9382
9383    /**
9384     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
9385     * treat them as such.
9386     * @hide
9387     */
9388    public void getOutsets(Rect outOutsetRect) {
9389        if (mAttachInfo != null) {
9390            outOutsetRect.set(mAttachInfo.mOutsets);
9391        } else {
9392            outOutsetRect.setEmpty();
9393        }
9394    }
9395
9396    /**
9397     * Returns the visibility status for this view.
9398     *
9399     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9400     * @attr ref android.R.styleable#View_visibility
9401     */
9402    @ViewDebug.ExportedProperty(mapping = {
9403        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
9404        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
9405        @ViewDebug.IntToString(from = GONE,      to = "GONE")
9406    })
9407    @Visibility
9408    public int getVisibility() {
9409        return mViewFlags & VISIBILITY_MASK;
9410    }
9411
9412    /**
9413     * Set the visibility state of this view.
9414     *
9415     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9416     * @attr ref android.R.styleable#View_visibility
9417     */
9418    @RemotableViewMethod
9419    public void setVisibility(@Visibility int visibility) {
9420        setFlags(visibility, VISIBILITY_MASK);
9421    }
9422
9423    /**
9424     * Returns the enabled status for this view. The interpretation of the
9425     * enabled state varies by subclass.
9426     *
9427     * @return True if this view is enabled, false otherwise.
9428     */
9429    @ViewDebug.ExportedProperty
9430    public boolean isEnabled() {
9431        return (mViewFlags & ENABLED_MASK) == ENABLED;
9432    }
9433
9434    /**
9435     * Set the enabled state of this view. The interpretation of the enabled
9436     * state varies by subclass.
9437     *
9438     * @param enabled True if this view is enabled, false otherwise.
9439     */
9440    @RemotableViewMethod
9441    public void setEnabled(boolean enabled) {
9442        if (enabled == isEnabled()) return;
9443
9444        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9445
9446        /*
9447         * The View most likely has to change its appearance, so refresh
9448         * the drawable state.
9449         */
9450        refreshDrawableState();
9451
9452        // Invalidate too, since the default behavior for views is to be
9453        // be drawn at 50% alpha rather than to change the drawable.
9454        invalidate(true);
9455
9456        if (!enabled) {
9457            cancelPendingInputEvents();
9458        }
9459    }
9460
9461    /**
9462     * Set whether this view can receive the focus.
9463     * <p>
9464     * Setting this to false will also ensure that this view is not focusable
9465     * in touch mode.
9466     *
9467     * @param focusable If true, this view can receive the focus.
9468     *
9469     * @see #setFocusableInTouchMode(boolean)
9470     * @see #setFocusable(int)
9471     * @attr ref android.R.styleable#View_focusable
9472     */
9473    public void setFocusable(boolean focusable) {
9474        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9475    }
9476
9477    /**
9478     * Sets whether this view can receive focus.
9479     * <p>
9480     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9481     * automatically based on the view's interactivity. This is the default.
9482     * <p>
9483     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9484     * in touch mode.
9485     *
9486     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9487     *                  or {@link #FOCUSABLE_AUTO}.
9488     * @see #setFocusableInTouchMode(boolean)
9489     * @attr ref android.R.styleable#View_focusable
9490     */
9491    public void setFocusable(@Focusable int focusable) {
9492        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9493            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9494        }
9495        setFlags(focusable, FOCUSABLE_MASK);
9496    }
9497
9498    /**
9499     * Set whether this view can receive focus while in touch mode.
9500     *
9501     * Setting this to true will also ensure that this view is focusable.
9502     *
9503     * @param focusableInTouchMode If true, this view can receive the focus while
9504     *   in touch mode.
9505     *
9506     * @see #setFocusable(boolean)
9507     * @attr ref android.R.styleable#View_focusableInTouchMode
9508     */
9509    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9510        // Focusable in touch mode should always be set before the focusable flag
9511        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9512        // which, in touch mode, will not successfully request focus on this view
9513        // because the focusable in touch mode flag is not set
9514        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9515
9516        // Clear FOCUSABLE_AUTO if set.
9517        if (focusableInTouchMode) {
9518            // Clears FOCUSABLE_AUTO if set.
9519            setFlags(FOCUSABLE, FOCUSABLE_MASK);
9520        }
9521    }
9522
9523    /**
9524     * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
9525     * to autofill the view with the user's data.
9526     *
9527     * <p>Typically, there is only one way to autofill a view, but there could be more than one.
9528     * For example, if the application accepts either an username or email address to identify
9529     * an user.
9530     *
9531     * <p>These hints are not validated by the Android System, but passed "as is" to the service.
9532     * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
9533     * constants such as:
9534     * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
9535     * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
9536     * {@link #AUTOFILL_HINT_NAME},
9537     * {@link #AUTOFILL_HINT_PHONE},
9538     * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
9539     * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
9540     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
9541     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
9542     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
9543     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
9544     *
9545     * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
9546     * @attr ref android.R.styleable#View_autofillHints
9547     */
9548    public void setAutofillHints(@Nullable String... autofillHints) {
9549        if (autofillHints == null || autofillHints.length == 0) {
9550            mAutofillHints = null;
9551        } else {
9552            mAutofillHints = autofillHints;
9553        }
9554    }
9555
9556    /**
9557     * @hide
9558     */
9559    @TestApi
9560    public void setAutofilled(boolean isAutofilled) {
9561        boolean wasChanged = isAutofilled != isAutofilled();
9562
9563        if (wasChanged) {
9564            if (isAutofilled) {
9565                mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
9566            } else {
9567                mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
9568            }
9569
9570            invalidate();
9571        }
9572    }
9573
9574    /**
9575     * Set whether this view should have sound effects enabled for events such as
9576     * clicking and touching.
9577     *
9578     * <p>You may wish to disable sound effects for a view if you already play sounds,
9579     * for instance, a dial key that plays dtmf tones.
9580     *
9581     * @param soundEffectsEnabled whether sound effects are enabled for this view.
9582     * @see #isSoundEffectsEnabled()
9583     * @see #playSoundEffect(int)
9584     * @attr ref android.R.styleable#View_soundEffectsEnabled
9585     */
9586    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9587        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9588    }
9589
9590    /**
9591     * @return whether this view should have sound effects enabled for events such as
9592     *     clicking and touching.
9593     *
9594     * @see #setSoundEffectsEnabled(boolean)
9595     * @see #playSoundEffect(int)
9596     * @attr ref android.R.styleable#View_soundEffectsEnabled
9597     */
9598    @ViewDebug.ExportedProperty
9599    public boolean isSoundEffectsEnabled() {
9600        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9601    }
9602
9603    /**
9604     * Set whether this view should have haptic feedback for events such as
9605     * long presses.
9606     *
9607     * <p>You may wish to disable haptic feedback if your view already controls
9608     * its own haptic feedback.
9609     *
9610     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9611     * @see #isHapticFeedbackEnabled()
9612     * @see #performHapticFeedback(int)
9613     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9614     */
9615    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9616        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9617    }
9618
9619    /**
9620     * @return whether this view should have haptic feedback enabled for events
9621     * long presses.
9622     *
9623     * @see #setHapticFeedbackEnabled(boolean)
9624     * @see #performHapticFeedback(int)
9625     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9626     */
9627    @ViewDebug.ExportedProperty
9628    public boolean isHapticFeedbackEnabled() {
9629        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9630    }
9631
9632    /**
9633     * Returns the layout direction for this view.
9634     *
9635     * @return One of {@link #LAYOUT_DIRECTION_LTR},
9636     *   {@link #LAYOUT_DIRECTION_RTL},
9637     *   {@link #LAYOUT_DIRECTION_INHERIT} or
9638     *   {@link #LAYOUT_DIRECTION_LOCALE}.
9639     *
9640     * @attr ref android.R.styleable#View_layoutDirection
9641     *
9642     * @hide
9643     */
9644    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9645        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9646        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9647        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9648        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9649    })
9650    @LayoutDir
9651    public int getRawLayoutDirection() {
9652        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9653    }
9654
9655    /**
9656     * Set the layout direction for this view. This will propagate a reset of layout direction
9657     * resolution to the view's children and resolve layout direction for this view.
9658     *
9659     * @param layoutDirection the layout direction to set. Should be one of:
9660     *
9661     * {@link #LAYOUT_DIRECTION_LTR},
9662     * {@link #LAYOUT_DIRECTION_RTL},
9663     * {@link #LAYOUT_DIRECTION_INHERIT},
9664     * {@link #LAYOUT_DIRECTION_LOCALE}.
9665     *
9666     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9667     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9668     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9669     *
9670     * @attr ref android.R.styleable#View_layoutDirection
9671     */
9672    @RemotableViewMethod
9673    public void setLayoutDirection(@LayoutDir int layoutDirection) {
9674        if (getRawLayoutDirection() != layoutDirection) {
9675            // Reset the current layout direction and the resolved one
9676            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9677            resetRtlProperties();
9678            // Set the new layout direction (filtered)
9679            mPrivateFlags2 |=
9680                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9681            // We need to resolve all RTL properties as they all depend on layout direction
9682            resolveRtlPropertiesIfNeeded();
9683            requestLayout();
9684            invalidate(true);
9685        }
9686    }
9687
9688    /**
9689     * Returns the resolved layout direction for this view.
9690     *
9691     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9692     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9693     *
9694     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9695     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9696     *
9697     * @attr ref android.R.styleable#View_layoutDirection
9698     */
9699    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9700        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9701        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9702    })
9703    @ResolvedLayoutDir
9704    public int getLayoutDirection() {
9705        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9706        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9707            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9708            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9709        }
9710        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9711                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9712    }
9713
9714    /**
9715     * Indicates whether or not this view's layout is right-to-left. This is resolved from
9716     * layout attribute and/or the inherited value from the parent
9717     *
9718     * @return true if the layout is right-to-left.
9719     *
9720     * @hide
9721     */
9722    @ViewDebug.ExportedProperty(category = "layout")
9723    public boolean isLayoutRtl() {
9724        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9725    }
9726
9727    /**
9728     * Indicates whether the view is currently tracking transient state that the
9729     * app should not need to concern itself with saving and restoring, but that
9730     * the framework should take special note to preserve when possible.
9731     *
9732     * <p>A view with transient state cannot be trivially rebound from an external
9733     * data source, such as an adapter binding item views in a list. This may be
9734     * because the view is performing an animation, tracking user selection
9735     * of content, or similar.</p>
9736     *
9737     * @return true if the view has transient state
9738     */
9739    @ViewDebug.ExportedProperty(category = "layout")
9740    public boolean hasTransientState() {
9741        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9742    }
9743
9744    /**
9745     * Set whether this view is currently tracking transient state that the
9746     * framework should attempt to preserve when possible. This flag is reference counted,
9747     * so every call to setHasTransientState(true) should be paired with a later call
9748     * to setHasTransientState(false).
9749     *
9750     * <p>A view with transient state cannot be trivially rebound from an external
9751     * data source, such as an adapter binding item views in a list. This may be
9752     * because the view is performing an animation, tracking user selection
9753     * of content, or similar.</p>
9754     *
9755     * @param hasTransientState true if this view has transient state
9756     */
9757    public void setHasTransientState(boolean hasTransientState) {
9758        final boolean oldHasTransientState = hasTransientState();
9759        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9760                mTransientStateCount - 1;
9761        if (mTransientStateCount < 0) {
9762            mTransientStateCount = 0;
9763            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9764                    "unmatched pair of setHasTransientState calls");
9765        } else if ((hasTransientState && mTransientStateCount == 1) ||
9766                (!hasTransientState && mTransientStateCount == 0)) {
9767            // update flag if we've just incremented up from 0 or decremented down to 0
9768            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9769                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9770            final boolean newHasTransientState = hasTransientState();
9771            if (mParent != null && newHasTransientState != oldHasTransientState) {
9772                try {
9773                    mParent.childHasTransientStateChanged(this, newHasTransientState);
9774                } catch (AbstractMethodError e) {
9775                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9776                            " does not fully implement ViewParent", e);
9777                }
9778            }
9779        }
9780    }
9781
9782    /**
9783     * Returns true if this view is currently attached to a window.
9784     */
9785    public boolean isAttachedToWindow() {
9786        return mAttachInfo != null;
9787    }
9788
9789    /**
9790     * Returns true if this view has been through at least one layout since it
9791     * was last attached to or detached from a window.
9792     */
9793    public boolean isLaidOut() {
9794        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9795    }
9796
9797    /**
9798     * If this view doesn't do any drawing on its own, set this flag to
9799     * allow further optimizations. By default, this flag is not set on
9800     * View, but could be set on some View subclasses such as ViewGroup.
9801     *
9802     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9803     * you should clear this flag.
9804     *
9805     * @param willNotDraw whether or not this View draw on its own
9806     */
9807    public void setWillNotDraw(boolean willNotDraw) {
9808        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9809    }
9810
9811    /**
9812     * Returns whether or not this View draws on its own.
9813     *
9814     * @return true if this view has nothing to draw, false otherwise
9815     */
9816    @ViewDebug.ExportedProperty(category = "drawing")
9817    public boolean willNotDraw() {
9818        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9819    }
9820
9821    /**
9822     * When a View's drawing cache is enabled, drawing is redirected to an
9823     * offscreen bitmap. Some views, like an ImageView, must be able to
9824     * bypass this mechanism if they already draw a single bitmap, to avoid
9825     * unnecessary usage of the memory.
9826     *
9827     * @param willNotCacheDrawing true if this view does not cache its
9828     *        drawing, false otherwise
9829     */
9830    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9831        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9832    }
9833
9834    /**
9835     * Returns whether or not this View can cache its drawing or not.
9836     *
9837     * @return true if this view does not cache its drawing, false otherwise
9838     */
9839    @ViewDebug.ExportedProperty(category = "drawing")
9840    public boolean willNotCacheDrawing() {
9841        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9842    }
9843
9844    /**
9845     * Indicates whether this view reacts to click events or not.
9846     *
9847     * @return true if the view is clickable, false otherwise
9848     *
9849     * @see #setClickable(boolean)
9850     * @attr ref android.R.styleable#View_clickable
9851     */
9852    @ViewDebug.ExportedProperty
9853    public boolean isClickable() {
9854        return (mViewFlags & CLICKABLE) == CLICKABLE;
9855    }
9856
9857    /**
9858     * Enables or disables click events for this view. When a view
9859     * is clickable it will change its state to "pressed" on every click.
9860     * Subclasses should set the view clickable to visually react to
9861     * user's clicks.
9862     *
9863     * @param clickable true to make the view clickable, false otherwise
9864     *
9865     * @see #isClickable()
9866     * @attr ref android.R.styleable#View_clickable
9867     */
9868    public void setClickable(boolean clickable) {
9869        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9870    }
9871
9872    /**
9873     * Indicates whether this view reacts to long click events or not.
9874     *
9875     * @return true if the view is long clickable, false otherwise
9876     *
9877     * @see #setLongClickable(boolean)
9878     * @attr ref android.R.styleable#View_longClickable
9879     */
9880    public boolean isLongClickable() {
9881        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9882    }
9883
9884    /**
9885     * Enables or disables long click events for this view. When a view is long
9886     * clickable it reacts to the user holding down the button for a longer
9887     * duration than a tap. This event can either launch the listener or a
9888     * context menu.
9889     *
9890     * @param longClickable true to make the view long clickable, false otherwise
9891     * @see #isLongClickable()
9892     * @attr ref android.R.styleable#View_longClickable
9893     */
9894    public void setLongClickable(boolean longClickable) {
9895        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9896    }
9897
9898    /**
9899     * Indicates whether this view reacts to context clicks or not.
9900     *
9901     * @return true if the view is context clickable, false otherwise
9902     * @see #setContextClickable(boolean)
9903     * @attr ref android.R.styleable#View_contextClickable
9904     */
9905    public boolean isContextClickable() {
9906        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9907    }
9908
9909    /**
9910     * Enables or disables context clicking for this view. This event can launch the listener.
9911     *
9912     * @param contextClickable true to make the view react to a context click, false otherwise
9913     * @see #isContextClickable()
9914     * @attr ref android.R.styleable#View_contextClickable
9915     */
9916    public void setContextClickable(boolean contextClickable) {
9917        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9918    }
9919
9920    /**
9921     * Sets the pressed state for this view and provides a touch coordinate for
9922     * animation hinting.
9923     *
9924     * @param pressed Pass true to set the View's internal state to "pressed",
9925     *            or false to reverts the View's internal state from a
9926     *            previously set "pressed" state.
9927     * @param x The x coordinate of the touch that caused the press
9928     * @param y The y coordinate of the touch that caused the press
9929     */
9930    private void setPressed(boolean pressed, float x, float y) {
9931        if (pressed) {
9932            drawableHotspotChanged(x, y);
9933        }
9934
9935        setPressed(pressed);
9936    }
9937
9938    /**
9939     * Sets the pressed state for this view.
9940     *
9941     * @see #isClickable()
9942     * @see #setClickable(boolean)
9943     *
9944     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9945     *        the View's internal state from a previously set "pressed" state.
9946     */
9947    public void setPressed(boolean pressed) {
9948        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9949
9950        if (pressed) {
9951            mPrivateFlags |= PFLAG_PRESSED;
9952        } else {
9953            mPrivateFlags &= ~PFLAG_PRESSED;
9954        }
9955
9956        if (needsRefresh) {
9957            refreshDrawableState();
9958        }
9959        dispatchSetPressed(pressed);
9960    }
9961
9962    /**
9963     * Dispatch setPressed to all of this View's children.
9964     *
9965     * @see #setPressed(boolean)
9966     *
9967     * @param pressed The new pressed state
9968     */
9969    protected void dispatchSetPressed(boolean pressed) {
9970    }
9971
9972    /**
9973     * Indicates whether the view is currently in pressed state. Unless
9974     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9975     * the pressed state.
9976     *
9977     * @see #setPressed(boolean)
9978     * @see #isClickable()
9979     * @see #setClickable(boolean)
9980     *
9981     * @return true if the view is currently pressed, false otherwise
9982     */
9983    @ViewDebug.ExportedProperty
9984    public boolean isPressed() {
9985        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9986    }
9987
9988    /**
9989     * @hide
9990     * Indicates whether this view will participate in data collection through
9991     * {@link ViewStructure}.  If true, it will not provide any data
9992     * for itself or its children.  If false, the normal data collection will be allowed.
9993     *
9994     * @return Returns false if assist data collection is not blocked, else true.
9995     *
9996     * @see #setAssistBlocked(boolean)
9997     * @attr ref android.R.styleable#View_assistBlocked
9998     */
9999    public boolean isAssistBlocked() {
10000        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
10001    }
10002
10003    /**
10004     * @hide
10005     * Controls whether assist data collection from this view and its children is enabled
10006     * (that is, whether {@link #onProvideStructure} and
10007     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
10008     * allowing normal assist collection.  Setting this to false will disable assist collection.
10009     *
10010     * @param enabled Set to true to <em>disable</em> assist data collection, or false
10011     * (the default) to allow it.
10012     *
10013     * @see #isAssistBlocked()
10014     * @see #onProvideStructure
10015     * @see #onProvideVirtualStructure
10016     * @attr ref android.R.styleable#View_assistBlocked
10017     */
10018    public void setAssistBlocked(boolean enabled) {
10019        if (enabled) {
10020            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
10021        } else {
10022            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
10023        }
10024    }
10025
10026    /**
10027     * Indicates whether this view will save its state (that is,
10028     * whether its {@link #onSaveInstanceState} method will be called).
10029     *
10030     * @return Returns true if the view state saving is enabled, else false.
10031     *
10032     * @see #setSaveEnabled(boolean)
10033     * @attr ref android.R.styleable#View_saveEnabled
10034     */
10035    public boolean isSaveEnabled() {
10036        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
10037    }
10038
10039    /**
10040     * Controls whether the saving of this view's state is
10041     * enabled (that is, whether its {@link #onSaveInstanceState} method
10042     * will be called).  Note that even if freezing is enabled, the
10043     * view still must have an id assigned to it (via {@link #setId(int)})
10044     * for its state to be saved.  This flag can only disable the
10045     * saving of this view; any child views may still have their state saved.
10046     *
10047     * @param enabled Set to false to <em>disable</em> state saving, or true
10048     * (the default) to allow it.
10049     *
10050     * @see #isSaveEnabled()
10051     * @see #setId(int)
10052     * @see #onSaveInstanceState()
10053     * @attr ref android.R.styleable#View_saveEnabled
10054     */
10055    public void setSaveEnabled(boolean enabled) {
10056        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
10057    }
10058
10059    /**
10060     * Gets whether the framework should discard touches when the view's
10061     * window is obscured by another visible window.
10062     * Refer to the {@link View} security documentation for more details.
10063     *
10064     * @return True if touch filtering is enabled.
10065     *
10066     * @see #setFilterTouchesWhenObscured(boolean)
10067     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
10068     */
10069    @ViewDebug.ExportedProperty
10070    public boolean getFilterTouchesWhenObscured() {
10071        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
10072    }
10073
10074    /**
10075     * Sets whether the framework should discard touches when the view's
10076     * window is obscured by another visible window.
10077     * Refer to the {@link View} security documentation for more details.
10078     *
10079     * @param enabled True if touch filtering should be enabled.
10080     *
10081     * @see #getFilterTouchesWhenObscured
10082     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
10083     */
10084    public void setFilterTouchesWhenObscured(boolean enabled) {
10085        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
10086                FILTER_TOUCHES_WHEN_OBSCURED);
10087    }
10088
10089    /**
10090     * Indicates whether the entire hierarchy under this view will save its
10091     * state when a state saving traversal occurs from its parent.  The default
10092     * is true; if false, these views will not be saved unless
10093     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10094     *
10095     * @return Returns true if the view state saving from parent is enabled, else false.
10096     *
10097     * @see #setSaveFromParentEnabled(boolean)
10098     */
10099    public boolean isSaveFromParentEnabled() {
10100        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
10101    }
10102
10103    /**
10104     * Controls whether the entire hierarchy under this view will save its
10105     * state when a state saving traversal occurs from its parent.  The default
10106     * is true; if false, these views will not be saved unless
10107     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10108     *
10109     * @param enabled Set to false to <em>disable</em> state saving, or true
10110     * (the default) to allow it.
10111     *
10112     * @see #isSaveFromParentEnabled()
10113     * @see #setId(int)
10114     * @see #onSaveInstanceState()
10115     */
10116    public void setSaveFromParentEnabled(boolean enabled) {
10117        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
10118    }
10119
10120
10121    /**
10122     * Returns whether this View is currently able to take focus.
10123     *
10124     * @return True if this view can take focus, or false otherwise.
10125     */
10126    @ViewDebug.ExportedProperty(category = "focus")
10127    public final boolean isFocusable() {
10128        return FOCUSABLE == (mViewFlags & FOCUSABLE);
10129    }
10130
10131    /**
10132     * Returns the focusable setting for this view.
10133     *
10134     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
10135     * @attr ref android.R.styleable#View_focusable
10136     */
10137    @ViewDebug.ExportedProperty(mapping = {
10138            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
10139            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
10140            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
10141            }, category = "focus")
10142    @Focusable
10143    public int getFocusable() {
10144        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
10145    }
10146
10147    /**
10148     * When a view is focusable, it may not want to take focus when in touch mode.
10149     * For example, a button would like focus when the user is navigating via a D-pad
10150     * so that the user can click on it, but once the user starts touching the screen,
10151     * the button shouldn't take focus
10152     * @return Whether the view is focusable in touch mode.
10153     * @attr ref android.R.styleable#View_focusableInTouchMode
10154     */
10155    @ViewDebug.ExportedProperty(category = "focus")
10156    public final boolean isFocusableInTouchMode() {
10157        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
10158    }
10159
10160    /**
10161     * Find the nearest view in the specified direction that can take focus.
10162     * This does not actually give focus to that view.
10163     *
10164     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10165     *
10166     * @return The nearest focusable in the specified direction, or null if none
10167     *         can be found.
10168     */
10169    public View focusSearch(@FocusRealDirection int direction) {
10170        if (mParent != null) {
10171            return mParent.focusSearch(this, direction);
10172        } else {
10173            return null;
10174        }
10175    }
10176
10177    /**
10178     * Returns whether this View is a root of a keyboard navigation cluster.
10179     *
10180     * @return True if this view is a root of a cluster, or false otherwise.
10181     * @attr ref android.R.styleable#View_keyboardNavigationCluster
10182     */
10183    @ViewDebug.ExportedProperty(category = "focus")
10184    public final boolean isKeyboardNavigationCluster() {
10185        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
10186    }
10187
10188    /**
10189     * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
10190     * will be ignored.
10191     *
10192     * @return the keyboard navigation cluster that this view is in (can be this view)
10193     *         or {@code null} if not in one
10194     */
10195    View findKeyboardNavigationCluster() {
10196        if (mParent instanceof View) {
10197            View cluster = ((View) mParent).findKeyboardNavigationCluster();
10198            if (cluster != null) {
10199                return cluster;
10200            } else if (isKeyboardNavigationCluster()) {
10201                return this;
10202            }
10203        }
10204        return null;
10205    }
10206
10207    /**
10208     * Set whether this view is a root of a keyboard navigation cluster.
10209     *
10210     * @param isCluster If true, this view is a root of a cluster.
10211     *
10212     * @attr ref android.R.styleable#View_keyboardNavigationCluster
10213     */
10214    public void setKeyboardNavigationCluster(boolean isCluster) {
10215        if (isCluster) {
10216            mPrivateFlags3 |= PFLAG3_CLUSTER;
10217        } else {
10218            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
10219        }
10220    }
10221
10222    /**
10223     * Sets this View as the one which receives focus the next time cluster navigation jumps
10224     * to the cluster containing this View. This does NOT change focus even if the cluster
10225     * containing this view is current.
10226     *
10227     * @hide
10228     */
10229    @TestApi
10230    public final void setFocusedInCluster() {
10231        setFocusedInCluster(findKeyboardNavigationCluster());
10232    }
10233
10234    private void setFocusedInCluster(View cluster) {
10235        if (this instanceof ViewGroup) {
10236            ((ViewGroup) this).mFocusedInCluster = null;
10237        }
10238        if (cluster == this) {
10239            return;
10240        }
10241        ViewParent parent = mParent;
10242        View child = this;
10243        while (parent instanceof ViewGroup) {
10244            ((ViewGroup) parent).mFocusedInCluster = child;
10245            if (parent == cluster) {
10246                break;
10247            }
10248            child = (View) parent;
10249            parent = parent.getParent();
10250        }
10251    }
10252
10253    private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
10254        if (oldFocus != null) {
10255            View oldCluster = oldFocus.findKeyboardNavigationCluster();
10256            View cluster = findKeyboardNavigationCluster();
10257            if (oldCluster != cluster) {
10258                // Going from one cluster to another, so save last-focused.
10259                // This covers cluster jumps because they are always FOCUS_DOWN
10260                oldFocus.setFocusedInCluster(oldCluster);
10261                if (!(oldFocus.mParent instanceof ViewGroup)) {
10262                    return;
10263                }
10264                if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
10265                    // This is a result of ordered navigation so consider navigation through
10266                    // the previous cluster "complete" and clear its last-focused memory.
10267                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10268                } else if (oldFocus instanceof ViewGroup
10269                        && ((ViewGroup) oldFocus).getDescendantFocusability()
10270                                == ViewGroup.FOCUS_AFTER_DESCENDANTS
10271                        && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
10272                    // This means oldFocus is not focusable since it obviously has a focusable
10273                    // child (this). Don't restore focus to it in the future.
10274                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10275                }
10276            }
10277        }
10278    }
10279
10280    /**
10281     * Returns whether this View should receive focus when the focus is restored for the view
10282     * hierarchy containing this view.
10283     * <p>
10284     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10285     * window or serves as a target of cluster navigation.
10286     *
10287     * @see #restoreDefaultFocus()
10288     *
10289     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
10290     * @attr ref android.R.styleable#View_focusedByDefault
10291     */
10292    @ViewDebug.ExportedProperty(category = "focus")
10293    public final boolean isFocusedByDefault() {
10294        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
10295    }
10296
10297    /**
10298     * Sets whether this View should receive focus when the focus is restored for the view
10299     * hierarchy containing this view.
10300     * <p>
10301     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10302     * window or serves as a target of cluster navigation.
10303     *
10304     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
10305     *                           {@code false} otherwise.
10306     *
10307     * @see #restoreDefaultFocus()
10308     *
10309     * @attr ref android.R.styleable#View_focusedByDefault
10310     */
10311    public void setFocusedByDefault(boolean isFocusedByDefault) {
10312        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
10313            return;
10314        }
10315
10316        if (isFocusedByDefault) {
10317            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
10318        } else {
10319            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
10320        }
10321
10322        if (mParent instanceof ViewGroup) {
10323            if (isFocusedByDefault) {
10324                ((ViewGroup) mParent).setDefaultFocus(this);
10325            } else {
10326                ((ViewGroup) mParent).clearDefaultFocus(this);
10327            }
10328        }
10329    }
10330
10331    /**
10332     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
10333     *
10334     * @return {@code true} if this view has default focus, {@code false} otherwise
10335     */
10336    boolean hasDefaultFocus() {
10337        return isFocusedByDefault();
10338    }
10339
10340    /**
10341     * Find the nearest keyboard navigation cluster in the specified direction.
10342     * This does not actually give focus to that cluster.
10343     *
10344     * @param currentCluster The starting point of the search. Null means the current cluster is not
10345     *                       found yet
10346     * @param direction Direction to look
10347     *
10348     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
10349     *         can be found
10350     */
10351    public View keyboardNavigationClusterSearch(View currentCluster,
10352            @FocusDirection int direction) {
10353        if (isKeyboardNavigationCluster()) {
10354            currentCluster = this;
10355        }
10356        if (isRootNamespace()) {
10357            // Root namespace means we should consider ourselves the top of the
10358            // tree for group searching; otherwise we could be group searching
10359            // into other tabs.  see LocalActivityManager and TabHost for more info.
10360            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
10361                    this, currentCluster, direction);
10362        } else if (mParent != null) {
10363            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
10364        }
10365        return null;
10366    }
10367
10368    /**
10369     * This method is the last chance for the focused view and its ancestors to
10370     * respond to an arrow key. This is called when the focused view did not
10371     * consume the key internally, nor could the view system find a new view in
10372     * the requested direction to give focus to.
10373     *
10374     * @param focused The currently focused view.
10375     * @param direction The direction focus wants to move. One of FOCUS_UP,
10376     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
10377     * @return True if the this view consumed this unhandled move.
10378     */
10379    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
10380        return false;
10381    }
10382
10383    /**
10384     * Sets whether this View should use a default focus highlight when it gets focused but doesn't
10385     * have {@link android.R.attr#state_focused} defined in its background.
10386     *
10387     * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
10388     *                                      highlight, {@code false} otherwise.
10389     *
10390     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10391     */
10392    public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
10393        mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
10394    }
10395
10396    /**
10397
10398    /**
10399     * Returns whether this View should use a default focus highlight when it gets focused but
10400     * doesn't have {@link android.R.attr#state_focused} defined in its background.
10401     *
10402     * @return True if this View should use a default focus highlight.
10403     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10404     */
10405    @ViewDebug.ExportedProperty(category = "focus")
10406    public final boolean getDefaultFocusHighlightEnabled() {
10407        return mDefaultFocusHighlightEnabled;
10408    }
10409
10410    /**
10411     * If a user manually specified the next view id for a particular direction,
10412     * use the root to look up the view.
10413     * @param root The root view of the hierarchy containing this view.
10414     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
10415     * or FOCUS_BACKWARD.
10416     * @return The user specified next view, or null if there is none.
10417     */
10418    View findUserSetNextFocus(View root, @FocusDirection int direction) {
10419        switch (direction) {
10420            case FOCUS_LEFT:
10421                if (mNextFocusLeftId == View.NO_ID) return null;
10422                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
10423            case FOCUS_RIGHT:
10424                if (mNextFocusRightId == View.NO_ID) return null;
10425                return findViewInsideOutShouldExist(root, mNextFocusRightId);
10426            case FOCUS_UP:
10427                if (mNextFocusUpId == View.NO_ID) return null;
10428                return findViewInsideOutShouldExist(root, mNextFocusUpId);
10429            case FOCUS_DOWN:
10430                if (mNextFocusDownId == View.NO_ID) return null;
10431                return findViewInsideOutShouldExist(root, mNextFocusDownId);
10432            case FOCUS_FORWARD:
10433                if (mNextFocusForwardId == View.NO_ID) return null;
10434                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
10435            case FOCUS_BACKWARD: {
10436                if (mID == View.NO_ID) return null;
10437                final int id = mID;
10438                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
10439                    @Override
10440                    public boolean test(View t) {
10441                        return t.mNextFocusForwardId == id;
10442                    }
10443                });
10444            }
10445        }
10446        return null;
10447    }
10448
10449    /**
10450     * If a user manually specified the next keyboard-navigation cluster for a particular direction,
10451     * use the root to look up the view.
10452     *
10453     * @param root the root view of the hierarchy containing this view
10454     * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
10455     * @return the user-specified next cluster, or {@code null} if there is none
10456     */
10457    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
10458        switch (direction) {
10459            case FOCUS_FORWARD:
10460                if (mNextClusterForwardId == View.NO_ID) return null;
10461                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
10462            case FOCUS_BACKWARD: {
10463                if (mID == View.NO_ID) return null;
10464                final int id = mID;
10465                return root.findViewByPredicateInsideOut(this,
10466                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
10467            }
10468        }
10469        return null;
10470    }
10471
10472    private View findViewInsideOutShouldExist(View root, int id) {
10473        if (mMatchIdPredicate == null) {
10474            mMatchIdPredicate = new MatchIdPredicate();
10475        }
10476        mMatchIdPredicate.mId = id;
10477        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
10478        if (result == null) {
10479            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
10480        }
10481        return result;
10482    }
10483
10484    /**
10485     * Find and return all focusable views that are descendants of this view,
10486     * possibly including this view if it is focusable itself.
10487     *
10488     * @param direction The direction of the focus
10489     * @return A list of focusable views
10490     */
10491    public ArrayList<View> getFocusables(@FocusDirection int direction) {
10492        ArrayList<View> result = new ArrayList<View>(24);
10493        addFocusables(result, direction);
10494        return result;
10495    }
10496
10497    /**
10498     * Add any focusable views that are descendants of this view (possibly
10499     * including this view if it is focusable itself) to views.  If we are in touch mode,
10500     * only add views that are also focusable in touch mode.
10501     *
10502     * @param views Focusable views found so far
10503     * @param direction The direction of the focus
10504     */
10505    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10506        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10507    }
10508
10509    /**
10510     * Adds any focusable views that are descendants of this view (possibly
10511     * including this view if it is focusable itself) to views. This method
10512     * adds all focusable views regardless if we are in touch mode or
10513     * only views focusable in touch mode if we are in touch mode or
10514     * only views that can take accessibility focus if accessibility is enabled
10515     * depending on the focusable mode parameter.
10516     *
10517     * @param views Focusable views found so far or null if all we are interested is
10518     *        the number of focusables.
10519     * @param direction The direction of the focus.
10520     * @param focusableMode The type of focusables to be added.
10521     *
10522     * @see #FOCUSABLES_ALL
10523     * @see #FOCUSABLES_TOUCH_MODE
10524     */
10525    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10526            @FocusableMode int focusableMode) {
10527        if (views == null) {
10528            return;
10529        }
10530        if (!isFocusable()) {
10531            return;
10532        }
10533        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10534                && !isFocusableInTouchMode()) {
10535            return;
10536        }
10537        views.add(this);
10538    }
10539
10540    /**
10541     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10542     * including this view if it is a cluster root itself) to views.
10543     *
10544     * @param views Keyboard navigation cluster roots found so far
10545     * @param direction Direction to look
10546     */
10547    public void addKeyboardNavigationClusters(
10548            @NonNull Collection<View> views,
10549            int direction) {
10550        if (!isKeyboardNavigationCluster()) {
10551            return;
10552        }
10553        if (!hasFocusable()) {
10554            return;
10555        }
10556        views.add(this);
10557    }
10558
10559    /**
10560     * Finds the Views that contain given text. The containment is case insensitive.
10561     * The search is performed by either the text that the View renders or the content
10562     * description that describes the view for accessibility purposes and the view does
10563     * not render or both. Clients can specify how the search is to be performed via
10564     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10565     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10566     *
10567     * @param outViews The output list of matching Views.
10568     * @param searched The text to match against.
10569     *
10570     * @see #FIND_VIEWS_WITH_TEXT
10571     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10572     * @see #setContentDescription(CharSequence)
10573     */
10574    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10575            @FindViewFlags int flags) {
10576        if (getAccessibilityNodeProvider() != null) {
10577            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10578                outViews.add(this);
10579            }
10580        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10581                && (searched != null && searched.length() > 0)
10582                && (mContentDescription != null && mContentDescription.length() > 0)) {
10583            String searchedLowerCase = searched.toString().toLowerCase();
10584            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10585            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10586                outViews.add(this);
10587            }
10588        }
10589    }
10590
10591    /**
10592     * Find and return all touchable views that are descendants of this view,
10593     * possibly including this view if it is touchable itself.
10594     *
10595     * @return A list of touchable views
10596     */
10597    public ArrayList<View> getTouchables() {
10598        ArrayList<View> result = new ArrayList<View>();
10599        addTouchables(result);
10600        return result;
10601    }
10602
10603    /**
10604     * Add any touchable views that are descendants of this view (possibly
10605     * including this view if it is touchable itself) to views.
10606     *
10607     * @param views Touchable views found so far
10608     */
10609    public void addTouchables(ArrayList<View> views) {
10610        final int viewFlags = mViewFlags;
10611
10612        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10613                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10614                && (viewFlags & ENABLED_MASK) == ENABLED) {
10615            views.add(this);
10616        }
10617    }
10618
10619    /**
10620     * Returns whether this View is accessibility focused.
10621     *
10622     * @return True if this View is accessibility focused.
10623     */
10624    public boolean isAccessibilityFocused() {
10625        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10626    }
10627
10628    /**
10629     * Call this to try to give accessibility focus to this view.
10630     *
10631     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10632     * returns false or the view is no visible or the view already has accessibility
10633     * focus.
10634     *
10635     * See also {@link #focusSearch(int)}, which is what you call to say that you
10636     * have focus, and you want your parent to look for the next one.
10637     *
10638     * @return Whether this view actually took accessibility focus.
10639     *
10640     * @hide
10641     */
10642    public boolean requestAccessibilityFocus() {
10643        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10644        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10645            return false;
10646        }
10647        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10648            return false;
10649        }
10650        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10651            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10652            ViewRootImpl viewRootImpl = getViewRootImpl();
10653            if (viewRootImpl != null) {
10654                viewRootImpl.setAccessibilityFocus(this, null);
10655            }
10656            invalidate();
10657            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10658            return true;
10659        }
10660        return false;
10661    }
10662
10663    /**
10664     * Call this to try to clear accessibility focus of this view.
10665     *
10666     * See also {@link #focusSearch(int)}, which is what you call to say that you
10667     * have focus, and you want your parent to look for the next one.
10668     *
10669     * @hide
10670     */
10671    public void clearAccessibilityFocus() {
10672        clearAccessibilityFocusNoCallbacks(0);
10673
10674        // Clear the global reference of accessibility focus if this view or
10675        // any of its descendants had accessibility focus. This will NOT send
10676        // an event or update internal state if focus is cleared from a
10677        // descendant view, which may leave views in inconsistent states.
10678        final ViewRootImpl viewRootImpl = getViewRootImpl();
10679        if (viewRootImpl != null) {
10680            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10681            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10682                viewRootImpl.setAccessibilityFocus(null, null);
10683            }
10684        }
10685    }
10686
10687    private void sendAccessibilityHoverEvent(int eventType) {
10688        // Since we are not delivering to a client accessibility events from not
10689        // important views (unless the clinet request that) we need to fire the
10690        // event from the deepest view exposed to the client. As a consequence if
10691        // the user crosses a not exposed view the client will see enter and exit
10692        // of the exposed predecessor followed by and enter and exit of that same
10693        // predecessor when entering and exiting the not exposed descendant. This
10694        // is fine since the client has a clear idea which view is hovered at the
10695        // price of a couple more events being sent. This is a simple and
10696        // working solution.
10697        View source = this;
10698        while (true) {
10699            if (source.includeForAccessibility()) {
10700                source.sendAccessibilityEvent(eventType);
10701                return;
10702            }
10703            ViewParent parent = source.getParent();
10704            if (parent instanceof View) {
10705                source = (View) parent;
10706            } else {
10707                return;
10708            }
10709        }
10710    }
10711
10712    /**
10713     * Clears accessibility focus without calling any callback methods
10714     * normally invoked in {@link #clearAccessibilityFocus()}. This method
10715     * is used separately from that one for clearing accessibility focus when
10716     * giving this focus to another view.
10717     *
10718     * @param action The action, if any, that led to focus being cleared. Set to
10719     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10720     * the window.
10721     */
10722    void clearAccessibilityFocusNoCallbacks(int action) {
10723        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10724            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10725            invalidate();
10726            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10727                AccessibilityEvent event = AccessibilityEvent.obtain(
10728                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10729                event.setAction(action);
10730                if (mAccessibilityDelegate != null) {
10731                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10732                } else {
10733                    sendAccessibilityEventUnchecked(event);
10734                }
10735            }
10736        }
10737    }
10738
10739    /**
10740     * Call this to try to give focus to a specific view or to one of its
10741     * descendants.
10742     *
10743     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10744     * false), or if it is focusable and it is not focusable in touch mode
10745     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10746     *
10747     * See also {@link #focusSearch(int)}, which is what you call to say that you
10748     * have focus, and you want your parent to look for the next one.
10749     *
10750     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10751     * {@link #FOCUS_DOWN} and <code>null</code>.
10752     *
10753     * @return Whether this view or one of its descendants actually took focus.
10754     */
10755    public final boolean requestFocus() {
10756        return requestFocus(View.FOCUS_DOWN);
10757    }
10758
10759    /**
10760     * This will request focus for whichever View was last focused within this
10761     * cluster before a focus-jump out of it.
10762     *
10763     * @hide
10764     */
10765    @TestApi
10766    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10767        // Prioritize focusableByDefault over algorithmic focus selection.
10768        if (restoreDefaultFocus()) {
10769            return true;
10770        }
10771        return requestFocus(direction);
10772    }
10773
10774    /**
10775     * This will request focus for whichever View not in a cluster was last focused before a
10776     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10777     * the "first" focusable view it finds.
10778     *
10779     * @hide
10780     */
10781    @TestApi
10782    public boolean restoreFocusNotInCluster() {
10783        return requestFocus(View.FOCUS_DOWN);
10784    }
10785
10786    /**
10787     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10788     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10789     *
10790     * @return Whether this view or one of its descendants actually took focus
10791     */
10792    public boolean restoreDefaultFocus() {
10793        return requestFocus(View.FOCUS_DOWN);
10794    }
10795
10796    /**
10797     * Call this to try to give focus to a specific view or to one of its
10798     * descendants and give it a hint about what direction focus is heading.
10799     *
10800     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10801     * false), or if it is focusable and it is not focusable in touch mode
10802     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10803     *
10804     * See also {@link #focusSearch(int)}, which is what you call to say that you
10805     * have focus, and you want your parent to look for the next one.
10806     *
10807     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10808     * <code>null</code> set for the previously focused rectangle.
10809     *
10810     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10811     * @return Whether this view or one of its descendants actually took focus.
10812     */
10813    public final boolean requestFocus(int direction) {
10814        return requestFocus(direction, null);
10815    }
10816
10817    /**
10818     * Call this to try to give focus to a specific view or to one of its descendants
10819     * and give it hints about the direction and a specific rectangle that the focus
10820     * is coming from.  The rectangle can help give larger views a finer grained hint
10821     * about where focus is coming from, and therefore, where to show selection, or
10822     * forward focus change internally.
10823     *
10824     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10825     * false), or if it is focusable and it is not focusable in touch mode
10826     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10827     *
10828     * A View will not take focus if it is not visible.
10829     *
10830     * A View will not take focus if one of its parents has
10831     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10832     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10833     *
10834     * See also {@link #focusSearch(int)}, which is what you call to say that you
10835     * have focus, and you want your parent to look for the next one.
10836     *
10837     * You may wish to override this method if your custom {@link View} has an internal
10838     * {@link View} that it wishes to forward the request to.
10839     *
10840     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10841     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10842     *        to give a finer grained hint about where focus is coming from.  May be null
10843     *        if there is no hint.
10844     * @return Whether this view or one of its descendants actually took focus.
10845     */
10846    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10847        return requestFocusNoSearch(direction, previouslyFocusedRect);
10848    }
10849
10850    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10851        // need to be focusable
10852        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10853                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10854            return false;
10855        }
10856
10857        // need to be focusable in touch mode if in touch mode
10858        if (isInTouchMode() &&
10859            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10860               return false;
10861        }
10862
10863        // need to not have any parents blocking us
10864        if (hasAncestorThatBlocksDescendantFocus()) {
10865            return false;
10866        }
10867
10868        handleFocusGainInternal(direction, previouslyFocusedRect);
10869        return true;
10870    }
10871
10872    /**
10873     * Call this to try to give focus to a specific view or to one of its descendants. This is a
10874     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10875     * touch mode to request focus when they are touched.
10876     *
10877     * @return Whether this view or one of its descendants actually took focus.
10878     *
10879     * @see #isInTouchMode()
10880     *
10881     */
10882    public final boolean requestFocusFromTouch() {
10883        // Leave touch mode if we need to
10884        if (isInTouchMode()) {
10885            ViewRootImpl viewRoot = getViewRootImpl();
10886            if (viewRoot != null) {
10887                viewRoot.ensureTouchMode(false);
10888            }
10889        }
10890        return requestFocus(View.FOCUS_DOWN);
10891    }
10892
10893    /**
10894     * @return Whether any ancestor of this view blocks descendant focus.
10895     */
10896    private boolean hasAncestorThatBlocksDescendantFocus() {
10897        final boolean focusableInTouchMode = isFocusableInTouchMode();
10898        ViewParent ancestor = mParent;
10899        while (ancestor instanceof ViewGroup) {
10900            final ViewGroup vgAncestor = (ViewGroup) ancestor;
10901            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10902                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10903                return true;
10904            } else {
10905                ancestor = vgAncestor.getParent();
10906            }
10907        }
10908        return false;
10909    }
10910
10911    /**
10912     * Gets the mode for determining whether this View is important for accessibility.
10913     * A view is important for accessibility if it fires accessibility events and if it
10914     * is reported to accessibility services that query the screen.
10915     *
10916     * @return The mode for determining whether a view is important for accessibility, one
10917     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10918     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10919     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10920     *
10921     * @attr ref android.R.styleable#View_importantForAccessibility
10922     *
10923     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10924     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10925     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10926     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10927     */
10928    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10929            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10930            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10931            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10932            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10933                    to = "noHideDescendants")
10934        })
10935    public int getImportantForAccessibility() {
10936        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10937                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10938    }
10939
10940    /**
10941     * Sets the live region mode for this view. This indicates to accessibility
10942     * services whether they should automatically notify the user about changes
10943     * to the view's content description or text, or to the content descriptions
10944     * or text of the view's children (where applicable).
10945     * <p>
10946     * For example, in a login screen with a TextView that displays an "incorrect
10947     * password" notification, that view should be marked as a live region with
10948     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10949     * <p>
10950     * To disable change notifications for this view, use
10951     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10952     * mode for most views.
10953     * <p>
10954     * To indicate that the user should be notified of changes, use
10955     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10956     * <p>
10957     * If the view's changes should interrupt ongoing speech and notify the user
10958     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10959     *
10960     * @param mode The live region mode for this view, one of:
10961     *        <ul>
10962     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10963     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10964     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10965     *        </ul>
10966     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10967     */
10968    public void setAccessibilityLiveRegion(int mode) {
10969        if (mode != getAccessibilityLiveRegion()) {
10970            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10971            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10972                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10973            notifyViewAccessibilityStateChangedIfNeeded(
10974                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10975        }
10976    }
10977
10978    /**
10979     * Gets the live region mode for this View.
10980     *
10981     * @return The live region mode for the view.
10982     *
10983     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10984     *
10985     * @see #setAccessibilityLiveRegion(int)
10986     */
10987    public int getAccessibilityLiveRegion() {
10988        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10989                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10990    }
10991
10992    /**
10993     * Sets how to determine whether this view is important for accessibility
10994     * which is if it fires accessibility events and if it is reported to
10995     * accessibility services that query the screen.
10996     *
10997     * @param mode How to determine whether this view is important for accessibility.
10998     *
10999     * @attr ref android.R.styleable#View_importantForAccessibility
11000     *
11001     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
11002     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
11003     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
11004     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
11005     */
11006    public void setImportantForAccessibility(int mode) {
11007        final int oldMode = getImportantForAccessibility();
11008        if (mode != oldMode) {
11009            final boolean hideDescendants =
11010                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
11011
11012            // If this node or its descendants are no longer important, try to
11013            // clear accessibility focus.
11014            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
11015                final View focusHost = findAccessibilityFocusHost(hideDescendants);
11016                if (focusHost != null) {
11017                    focusHost.clearAccessibilityFocus();
11018                }
11019            }
11020
11021            // If we're moving between AUTO and another state, we might not need
11022            // to send a subtree changed notification. We'll store the computed
11023            // importance, since we'll need to check it later to make sure.
11024            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
11025                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
11026            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
11027            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
11028            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
11029                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
11030            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
11031                notifySubtreeAccessibilityStateChangedIfNeeded();
11032            } else {
11033                notifyViewAccessibilityStateChangedIfNeeded(
11034                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11035            }
11036        }
11037    }
11038
11039    /**
11040     * Returns the view within this view's hierarchy that is hosting
11041     * accessibility focus.
11042     *
11043     * @param searchDescendants whether to search for focus in descendant views
11044     * @return the view hosting accessibility focus, or {@code null}
11045     */
11046    private View findAccessibilityFocusHost(boolean searchDescendants) {
11047        if (isAccessibilityFocusedViewOrHost()) {
11048            return this;
11049        }
11050
11051        if (searchDescendants) {
11052            final ViewRootImpl viewRoot = getViewRootImpl();
11053            if (viewRoot != null) {
11054                final View focusHost = viewRoot.getAccessibilityFocusedHost();
11055                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
11056                    return focusHost;
11057                }
11058            }
11059        }
11060
11061        return null;
11062    }
11063
11064    /**
11065     * Computes whether this view should be exposed for accessibility. In
11066     * general, views that are interactive or provide information are exposed
11067     * while views that serve only as containers are hidden.
11068     * <p>
11069     * If an ancestor of this view has importance
11070     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
11071     * returns <code>false</code>.
11072     * <p>
11073     * Otherwise, the value is computed according to the view's
11074     * {@link #getImportantForAccessibility()} value:
11075     * <ol>
11076     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
11077     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
11078     * </code>
11079     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
11080     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
11081     * view satisfies any of the following:
11082     * <ul>
11083     * <li>Is actionable, e.g. {@link #isClickable()},
11084     * {@link #isLongClickable()}, or {@link #isFocusable()}
11085     * <li>Has an {@link AccessibilityDelegate}
11086     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
11087     * {@link OnKeyListener}, etc.
11088     * <li>Is an accessibility live region, e.g.
11089     * {@link #getAccessibilityLiveRegion()} is not
11090     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
11091     * </ul>
11092     * </ol>
11093     *
11094     * @return Whether the view is exposed for accessibility.
11095     * @see #setImportantForAccessibility(int)
11096     * @see #getImportantForAccessibility()
11097     */
11098    public boolean isImportantForAccessibility() {
11099        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
11100                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
11101        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
11102                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11103            return false;
11104        }
11105
11106        // Check parent mode to ensure we're not hidden.
11107        ViewParent parent = mParent;
11108        while (parent instanceof View) {
11109            if (((View) parent).getImportantForAccessibility()
11110                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11111                return false;
11112            }
11113            parent = parent.getParent();
11114        }
11115
11116        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
11117                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
11118                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
11119    }
11120
11121    /**
11122     * Gets the parent for accessibility purposes. Note that the parent for
11123     * accessibility is not necessary the immediate parent. It is the first
11124     * predecessor that is important for accessibility.
11125     *
11126     * @return The parent for accessibility purposes.
11127     */
11128    public ViewParent getParentForAccessibility() {
11129        if (mParent instanceof View) {
11130            View parentView = (View) mParent;
11131            if (parentView.includeForAccessibility()) {
11132                return mParent;
11133            } else {
11134                return mParent.getParentForAccessibility();
11135            }
11136        }
11137        return null;
11138    }
11139
11140    /**
11141     * Adds the children of this View relevant for accessibility to the given list
11142     * as output. Since some Views are not important for accessibility the added
11143     * child views are not necessarily direct children of this view, rather they are
11144     * the first level of descendants important for accessibility.
11145     *
11146     * @param outChildren The output list that will receive children for accessibility.
11147     */
11148    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
11149
11150    }
11151
11152    /**
11153     * Whether to regard this view for accessibility. A view is regarded for
11154     * accessibility if it is important for accessibility or the querying
11155     * accessibility service has explicitly requested that view not
11156     * important for accessibility are regarded.
11157     *
11158     * @return Whether to regard the view for accessibility.
11159     *
11160     * @hide
11161     */
11162    public boolean includeForAccessibility() {
11163        if (mAttachInfo != null) {
11164            return (mAttachInfo.mAccessibilityFetchFlags
11165                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
11166                    || isImportantForAccessibility();
11167        }
11168        return false;
11169    }
11170
11171    /**
11172     * Returns whether the View is considered actionable from
11173     * accessibility perspective. Such view are important for
11174     * accessibility.
11175     *
11176     * @return True if the view is actionable for accessibility.
11177     *
11178     * @hide
11179     */
11180    public boolean isActionableForAccessibility() {
11181        return (isClickable() || isLongClickable() || isFocusable());
11182    }
11183
11184    /**
11185     * Returns whether the View has registered callbacks which makes it
11186     * important for accessibility.
11187     *
11188     * @return True if the view is actionable for accessibility.
11189     */
11190    private boolean hasListenersForAccessibility() {
11191        ListenerInfo info = getListenerInfo();
11192        return mTouchDelegate != null || info.mOnKeyListener != null
11193                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
11194                || info.mOnHoverListener != null || info.mOnDragListener != null;
11195    }
11196
11197    /**
11198     * Notifies that the accessibility state of this view changed. The change
11199     * is local to this view and does not represent structural changes such
11200     * as children and parent. For example, the view became focusable. The
11201     * notification is at at most once every
11202     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11203     * to avoid unnecessary load to the system. Also once a view has a pending
11204     * notification this method is a NOP until the notification has been sent.
11205     *
11206     * @hide
11207     */
11208    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
11209        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11210            return;
11211        }
11212        // If this is a live region, we should send a subtree change event
11213        // from this view immediately. Otherwise, we can let it propagate up.
11214        if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) {
11215            final AccessibilityEvent event = AccessibilityEvent.obtain();
11216            event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
11217            event.setContentChangeTypes(changeType);
11218            sendAccessibilityEventUnchecked(event);
11219        } else if (mParent != null) {
11220            try {
11221                mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType);
11222            } catch (AbstractMethodError e) {
11223                Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11224                        " does not fully implement ViewParent", e);
11225            }
11226        }
11227    }
11228
11229    /**
11230     * Notifies that the accessibility state of this view changed. The change
11231     * is *not* local to this view and does represent structural changes such
11232     * as children and parent. For example, the view size changed. The
11233     * notification is at at most once every
11234     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11235     * to avoid unnecessary load to the system. Also once a view has a pending
11236     * notification this method is a NOP until the notification has been sent.
11237     *
11238     * @hide
11239     */
11240    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
11241        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11242            return;
11243        }
11244        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
11245            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11246            if (mParent != null) {
11247                try {
11248                    mParent.notifySubtreeAccessibilityStateChanged(
11249                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
11250                } catch (AbstractMethodError e) {
11251                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11252                            " does not fully implement ViewParent", e);
11253                }
11254            }
11255        }
11256    }
11257
11258    /**
11259     * Change the visibility of the View without triggering any other changes. This is
11260     * important for transitions, where visibility changes should not adjust focus or
11261     * trigger a new layout. This is only used when the visibility has already been changed
11262     * and we need a transient value during an animation. When the animation completes,
11263     * the original visibility value is always restored.
11264     *
11265     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11266     * @hide
11267     */
11268    public void setTransitionVisibility(@Visibility int visibility) {
11269        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
11270    }
11271
11272    /**
11273     * Reset the flag indicating the accessibility state of the subtree rooted
11274     * at this view changed.
11275     */
11276    void resetSubtreeAccessibilityStateChanged() {
11277        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11278    }
11279
11280    /**
11281     * Report an accessibility action to this view's parents for delegated processing.
11282     *
11283     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
11284     * call this method to delegate an accessibility action to a supporting parent. If the parent
11285     * returns true from its
11286     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
11287     * method this method will return true to signify that the action was consumed.</p>
11288     *
11289     * <p>This method is useful for implementing nested scrolling child views. If
11290     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
11291     * a custom view implementation may invoke this method to allow a parent to consume the
11292     * scroll first. If this method returns true the custom view should skip its own scrolling
11293     * behavior.</p>
11294     *
11295     * @param action Accessibility action to delegate
11296     * @param arguments Optional action arguments
11297     * @return true if the action was consumed by a parent
11298     */
11299    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
11300        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
11301            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
11302                return true;
11303            }
11304        }
11305        return false;
11306    }
11307
11308    /**
11309     * Performs the specified accessibility action on the view. For
11310     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
11311     * <p>
11312     * If an {@link AccessibilityDelegate} has been specified via calling
11313     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
11314     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
11315     * is responsible for handling this call.
11316     * </p>
11317     *
11318     * <p>The default implementation will delegate
11319     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
11320     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
11321     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
11322     *
11323     * @param action The action to perform.
11324     * @param arguments Optional action arguments.
11325     * @return Whether the action was performed.
11326     */
11327    public boolean performAccessibilityAction(int action, Bundle arguments) {
11328      if (mAccessibilityDelegate != null) {
11329          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
11330      } else {
11331          return performAccessibilityActionInternal(action, arguments);
11332      }
11333    }
11334
11335   /**
11336    * @see #performAccessibilityAction(int, Bundle)
11337    *
11338    * Note: Called from the default {@link AccessibilityDelegate}.
11339    *
11340    * @hide
11341    */
11342    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
11343        if (isNestedScrollingEnabled()
11344                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
11345                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
11346                || action == R.id.accessibilityActionScrollUp
11347                || action == R.id.accessibilityActionScrollLeft
11348                || action == R.id.accessibilityActionScrollDown
11349                || action == R.id.accessibilityActionScrollRight)) {
11350            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
11351                return true;
11352            }
11353        }
11354
11355        switch (action) {
11356            case AccessibilityNodeInfo.ACTION_CLICK: {
11357                if (isClickable()) {
11358                    performClick();
11359                    return true;
11360                }
11361            } break;
11362            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
11363                if (isLongClickable()) {
11364                    performLongClick();
11365                    return true;
11366                }
11367            } break;
11368            case AccessibilityNodeInfo.ACTION_FOCUS: {
11369                if (!hasFocus()) {
11370                    // Get out of touch mode since accessibility
11371                    // wants to move focus around.
11372                    getViewRootImpl().ensureTouchMode(false);
11373                    return requestFocus();
11374                }
11375            } break;
11376            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
11377                if (hasFocus()) {
11378                    clearFocus();
11379                    return !isFocused();
11380                }
11381            } break;
11382            case AccessibilityNodeInfo.ACTION_SELECT: {
11383                if (!isSelected()) {
11384                    setSelected(true);
11385                    return isSelected();
11386                }
11387            } break;
11388            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
11389                if (isSelected()) {
11390                    setSelected(false);
11391                    return !isSelected();
11392                }
11393            } break;
11394            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
11395                if (!isAccessibilityFocused()) {
11396                    return requestAccessibilityFocus();
11397                }
11398            } break;
11399            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
11400                if (isAccessibilityFocused()) {
11401                    clearAccessibilityFocus();
11402                    return true;
11403                }
11404            } break;
11405            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
11406                if (arguments != null) {
11407                    final int granularity = arguments.getInt(
11408                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11409                    final boolean extendSelection = arguments.getBoolean(
11410                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11411                    return traverseAtGranularity(granularity, true, extendSelection);
11412                }
11413            } break;
11414            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
11415                if (arguments != null) {
11416                    final int granularity = arguments.getInt(
11417                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11418                    final boolean extendSelection = arguments.getBoolean(
11419                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11420                    return traverseAtGranularity(granularity, false, extendSelection);
11421                }
11422            } break;
11423            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
11424                CharSequence text = getIterableTextForAccessibility();
11425                if (text == null) {
11426                    return false;
11427                }
11428                final int start = (arguments != null) ? arguments.getInt(
11429                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
11430                final int end = (arguments != null) ? arguments.getInt(
11431                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
11432                // Only cursor position can be specified (selection length == 0)
11433                if ((getAccessibilitySelectionStart() != start
11434                        || getAccessibilitySelectionEnd() != end)
11435                        && (start == end)) {
11436                    setAccessibilitySelection(start, end);
11437                    notifyViewAccessibilityStateChangedIfNeeded(
11438                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11439                    return true;
11440                }
11441            } break;
11442            case R.id.accessibilityActionShowOnScreen: {
11443                if (mAttachInfo != null) {
11444                    final Rect r = mAttachInfo.mTmpInvalRect;
11445                    getDrawingRect(r);
11446                    return requestRectangleOnScreen(r, true);
11447                }
11448            } break;
11449            case R.id.accessibilityActionContextClick: {
11450                if (isContextClickable()) {
11451                    performContextClick();
11452                    return true;
11453                }
11454            } break;
11455        }
11456        return false;
11457    }
11458
11459    private boolean traverseAtGranularity(int granularity, boolean forward,
11460            boolean extendSelection) {
11461        CharSequence text = getIterableTextForAccessibility();
11462        if (text == null || text.length() == 0) {
11463            return false;
11464        }
11465        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
11466        if (iterator == null) {
11467            return false;
11468        }
11469        int current = getAccessibilitySelectionEnd();
11470        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11471            current = forward ? 0 : text.length();
11472        }
11473        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
11474        if (range == null) {
11475            return false;
11476        }
11477        final int segmentStart = range[0];
11478        final int segmentEnd = range[1];
11479        int selectionStart;
11480        int selectionEnd;
11481        if (extendSelection && isAccessibilitySelectionExtendable()) {
11482            selectionStart = getAccessibilitySelectionStart();
11483            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11484                selectionStart = forward ? segmentStart : segmentEnd;
11485            }
11486            selectionEnd = forward ? segmentEnd : segmentStart;
11487        } else {
11488            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
11489        }
11490        setAccessibilitySelection(selectionStart, selectionEnd);
11491        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
11492                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
11493        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
11494        return true;
11495    }
11496
11497    /**
11498     * Gets the text reported for accessibility purposes.
11499     *
11500     * @return The accessibility text.
11501     *
11502     * @hide
11503     */
11504    public CharSequence getIterableTextForAccessibility() {
11505        return getContentDescription();
11506    }
11507
11508    /**
11509     * Gets whether accessibility selection can be extended.
11510     *
11511     * @return If selection is extensible.
11512     *
11513     * @hide
11514     */
11515    public boolean isAccessibilitySelectionExtendable() {
11516        return false;
11517    }
11518
11519    /**
11520     * @hide
11521     */
11522    public int getAccessibilitySelectionStart() {
11523        return mAccessibilityCursorPosition;
11524    }
11525
11526    /**
11527     * @hide
11528     */
11529    public int getAccessibilitySelectionEnd() {
11530        return getAccessibilitySelectionStart();
11531    }
11532
11533    /**
11534     * @hide
11535     */
11536    public void setAccessibilitySelection(int start, int end) {
11537        if (start ==  end && end == mAccessibilityCursorPosition) {
11538            return;
11539        }
11540        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11541            mAccessibilityCursorPosition = start;
11542        } else {
11543            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11544        }
11545        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11546    }
11547
11548    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11549            int fromIndex, int toIndex) {
11550        if (mParent == null) {
11551            return;
11552        }
11553        AccessibilityEvent event = AccessibilityEvent.obtain(
11554                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11555        onInitializeAccessibilityEvent(event);
11556        onPopulateAccessibilityEvent(event);
11557        event.setFromIndex(fromIndex);
11558        event.setToIndex(toIndex);
11559        event.setAction(action);
11560        event.setMovementGranularity(granularity);
11561        mParent.requestSendAccessibilityEvent(this, event);
11562    }
11563
11564    /**
11565     * @hide
11566     */
11567    public TextSegmentIterator getIteratorForGranularity(int granularity) {
11568        switch (granularity) {
11569            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11570                CharSequence text = getIterableTextForAccessibility();
11571                if (text != null && text.length() > 0) {
11572                    CharacterTextSegmentIterator iterator =
11573                        CharacterTextSegmentIterator.getInstance(
11574                                mContext.getResources().getConfiguration().locale);
11575                    iterator.initialize(text.toString());
11576                    return iterator;
11577                }
11578            } break;
11579            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11580                CharSequence text = getIterableTextForAccessibility();
11581                if (text != null && text.length() > 0) {
11582                    WordTextSegmentIterator iterator =
11583                        WordTextSegmentIterator.getInstance(
11584                                mContext.getResources().getConfiguration().locale);
11585                    iterator.initialize(text.toString());
11586                    return iterator;
11587                }
11588            } break;
11589            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11590                CharSequence text = getIterableTextForAccessibility();
11591                if (text != null && text.length() > 0) {
11592                    ParagraphTextSegmentIterator iterator =
11593                        ParagraphTextSegmentIterator.getInstance();
11594                    iterator.initialize(text.toString());
11595                    return iterator;
11596                }
11597            } break;
11598        }
11599        return null;
11600    }
11601
11602    /**
11603     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11604     * and {@link #onFinishTemporaryDetach()}.
11605     *
11606     * <p>This method always returns {@code true} when called directly or indirectly from
11607     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11608     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11609     * <ul>
11610     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11611     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11612     * </ul>
11613     * </p>
11614     *
11615     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11616     * and {@link #onFinishTemporaryDetach()}.
11617     */
11618    public final boolean isTemporarilyDetached() {
11619        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11620    }
11621
11622    /**
11623     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11624     * a container View.
11625     */
11626    @CallSuper
11627    public void dispatchStartTemporaryDetach() {
11628        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11629        notifyEnterOrExitForAutoFillIfNeeded(false);
11630        onStartTemporaryDetach();
11631    }
11632
11633    /**
11634     * This is called when a container is going to temporarily detach a child, with
11635     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11636     * It will either be followed by {@link #onFinishTemporaryDetach()} or
11637     * {@link #onDetachedFromWindow()} when the container is done.
11638     */
11639    public void onStartTemporaryDetach() {
11640        removeUnsetPressCallback();
11641        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11642    }
11643
11644    /**
11645     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11646     * a container View.
11647     */
11648    @CallSuper
11649    public void dispatchFinishTemporaryDetach() {
11650        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11651        onFinishTemporaryDetach();
11652        if (hasWindowFocus() && hasFocus()) {
11653            InputMethodManager.getInstance().focusIn(this);
11654        }
11655        notifyEnterOrExitForAutoFillIfNeeded(true);
11656    }
11657
11658    /**
11659     * Called after {@link #onStartTemporaryDetach} when the container is done
11660     * changing the view.
11661     */
11662    public void onFinishTemporaryDetach() {
11663    }
11664
11665    /**
11666     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11667     * for this view's window.  Returns null if the view is not currently attached
11668     * to the window.  Normally you will not need to use this directly, but
11669     * just use the standard high-level event callbacks like
11670     * {@link #onKeyDown(int, KeyEvent)}.
11671     */
11672    public KeyEvent.DispatcherState getKeyDispatcherState() {
11673        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11674    }
11675
11676    /**
11677     * Dispatch a key event before it is processed by any input method
11678     * associated with the view hierarchy.  This can be used to intercept
11679     * key events in special situations before the IME consumes them; a
11680     * typical example would be handling the BACK key to update the application's
11681     * UI instead of allowing the IME to see it and close itself.
11682     *
11683     * @param event The key event to be dispatched.
11684     * @return True if the event was handled, false otherwise.
11685     */
11686    public boolean dispatchKeyEventPreIme(KeyEvent event) {
11687        return onKeyPreIme(event.getKeyCode(), event);
11688    }
11689
11690    /**
11691     * Dispatch a key event to the next view on the focus path. This path runs
11692     * from the top of the view tree down to the currently focused view. If this
11693     * view has focus, it will dispatch to itself. Otherwise it will dispatch
11694     * the next node down the focus path. This method also fires any key
11695     * listeners.
11696     *
11697     * @param event The key event to be dispatched.
11698     * @return True if the event was handled, false otherwise.
11699     */
11700    public boolean dispatchKeyEvent(KeyEvent event) {
11701        if (mInputEventConsistencyVerifier != null) {
11702            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11703        }
11704
11705        // Give any attached key listener a first crack at the event.
11706        //noinspection SimplifiableIfStatement
11707        ListenerInfo li = mListenerInfo;
11708        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11709                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11710            return true;
11711        }
11712
11713        if (event.dispatch(this, mAttachInfo != null
11714                ? mAttachInfo.mKeyDispatchState : null, this)) {
11715            return true;
11716        }
11717
11718        if (mInputEventConsistencyVerifier != null) {
11719            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11720        }
11721        return false;
11722    }
11723
11724    /**
11725     * Dispatches a key shortcut event.
11726     *
11727     * @param event The key event to be dispatched.
11728     * @return True if the event was handled by the view, false otherwise.
11729     */
11730    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11731        return onKeyShortcut(event.getKeyCode(), event);
11732    }
11733
11734    /**
11735     * Pass the touch screen motion event down to the target view, or this
11736     * view if it is the target.
11737     *
11738     * @param event The motion event to be dispatched.
11739     * @return True if the event was handled by the view, false otherwise.
11740     */
11741    public boolean dispatchTouchEvent(MotionEvent event) {
11742        // If the event should be handled by accessibility focus first.
11743        if (event.isTargetAccessibilityFocus()) {
11744            // We don't have focus or no virtual descendant has it, do not handle the event.
11745            if (!isAccessibilityFocusedViewOrHost()) {
11746                return false;
11747            }
11748            // We have focus and got the event, then use normal event dispatch.
11749            event.setTargetAccessibilityFocus(false);
11750        }
11751
11752        boolean result = false;
11753
11754        if (mInputEventConsistencyVerifier != null) {
11755            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11756        }
11757
11758        final int actionMasked = event.getActionMasked();
11759        if (actionMasked == MotionEvent.ACTION_DOWN) {
11760            // Defensive cleanup for new gesture
11761            stopNestedScroll();
11762        }
11763
11764        if (onFilterTouchEventForSecurity(event)) {
11765            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11766                result = true;
11767            }
11768            //noinspection SimplifiableIfStatement
11769            ListenerInfo li = mListenerInfo;
11770            if (li != null && li.mOnTouchListener != null
11771                    && (mViewFlags & ENABLED_MASK) == ENABLED
11772                    && li.mOnTouchListener.onTouch(this, event)) {
11773                result = true;
11774            }
11775
11776            if (!result && onTouchEvent(event)) {
11777                result = true;
11778            }
11779        }
11780
11781        if (!result && mInputEventConsistencyVerifier != null) {
11782            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11783        }
11784
11785        // Clean up after nested scrolls if this is the end of a gesture;
11786        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11787        // of the gesture.
11788        if (actionMasked == MotionEvent.ACTION_UP ||
11789                actionMasked == MotionEvent.ACTION_CANCEL ||
11790                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11791            stopNestedScroll();
11792        }
11793
11794        return result;
11795    }
11796
11797    boolean isAccessibilityFocusedViewOrHost() {
11798        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11799                .getAccessibilityFocusedHost() == this);
11800    }
11801
11802    /**
11803     * Filter the touch event to apply security policies.
11804     *
11805     * @param event The motion event to be filtered.
11806     * @return True if the event should be dispatched, false if the event should be dropped.
11807     *
11808     * @see #getFilterTouchesWhenObscured
11809     */
11810    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11811        //noinspection RedundantIfStatement
11812        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11813                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11814            // Window is obscured, drop this touch.
11815            return false;
11816        }
11817        return true;
11818    }
11819
11820    /**
11821     * Pass a trackball motion event down to the focused view.
11822     *
11823     * @param event The motion event to be dispatched.
11824     * @return True if the event was handled by the view, false otherwise.
11825     */
11826    public boolean dispatchTrackballEvent(MotionEvent event) {
11827        if (mInputEventConsistencyVerifier != null) {
11828            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11829        }
11830
11831        return onTrackballEvent(event);
11832    }
11833
11834    /**
11835     * Pass a captured pointer event down to the focused view.
11836     *
11837     * @param event The motion event to be dispatched.
11838     * @return True if the event was handled by the view, false otherwise.
11839     */
11840    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11841        if (!hasPointerCapture()) {
11842            return false;
11843        }
11844        //noinspection SimplifiableIfStatement
11845        ListenerInfo li = mListenerInfo;
11846        if (li != null && li.mOnCapturedPointerListener != null
11847                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11848            return true;
11849        }
11850        return onCapturedPointerEvent(event);
11851    }
11852
11853    /**
11854     * Dispatch a generic motion event.
11855     * <p>
11856     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11857     * are delivered to the view under the pointer.  All other generic motion events are
11858     * delivered to the focused view.  Hover events are handled specially and are delivered
11859     * to {@link #onHoverEvent(MotionEvent)}.
11860     * </p>
11861     *
11862     * @param event The motion event to be dispatched.
11863     * @return True if the event was handled by the view, false otherwise.
11864     */
11865    public boolean dispatchGenericMotionEvent(MotionEvent event) {
11866        if (mInputEventConsistencyVerifier != null) {
11867            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11868        }
11869
11870        final int source = event.getSource();
11871        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11872            final int action = event.getAction();
11873            if (action == MotionEvent.ACTION_HOVER_ENTER
11874                    || action == MotionEvent.ACTION_HOVER_MOVE
11875                    || action == MotionEvent.ACTION_HOVER_EXIT) {
11876                if (dispatchHoverEvent(event)) {
11877                    return true;
11878                }
11879            } else if (dispatchGenericPointerEvent(event)) {
11880                return true;
11881            }
11882        } else if (dispatchGenericFocusedEvent(event)) {
11883            return true;
11884        }
11885
11886        if (dispatchGenericMotionEventInternal(event)) {
11887            return true;
11888        }
11889
11890        if (mInputEventConsistencyVerifier != null) {
11891            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11892        }
11893        return false;
11894    }
11895
11896    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11897        //noinspection SimplifiableIfStatement
11898        ListenerInfo li = mListenerInfo;
11899        if (li != null && li.mOnGenericMotionListener != null
11900                && (mViewFlags & ENABLED_MASK) == ENABLED
11901                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11902            return true;
11903        }
11904
11905        if (onGenericMotionEvent(event)) {
11906            return true;
11907        }
11908
11909        final int actionButton = event.getActionButton();
11910        switch (event.getActionMasked()) {
11911            case MotionEvent.ACTION_BUTTON_PRESS:
11912                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11913                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11914                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11915                    if (performContextClick(event.getX(), event.getY())) {
11916                        mInContextButtonPress = true;
11917                        setPressed(true, event.getX(), event.getY());
11918                        removeTapCallback();
11919                        removeLongPressCallback();
11920                        return true;
11921                    }
11922                }
11923                break;
11924
11925            case MotionEvent.ACTION_BUTTON_RELEASE:
11926                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11927                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11928                    mInContextButtonPress = false;
11929                    mIgnoreNextUpEvent = true;
11930                }
11931                break;
11932        }
11933
11934        if (mInputEventConsistencyVerifier != null) {
11935            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11936        }
11937        return false;
11938    }
11939
11940    /**
11941     * Dispatch a hover event.
11942     * <p>
11943     * Do not call this method directly.
11944     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11945     * </p>
11946     *
11947     * @param event The motion event to be dispatched.
11948     * @return True if the event was handled by the view, false otherwise.
11949     */
11950    protected boolean dispatchHoverEvent(MotionEvent event) {
11951        ListenerInfo li = mListenerInfo;
11952        //noinspection SimplifiableIfStatement
11953        if (li != null && li.mOnHoverListener != null
11954                && (mViewFlags & ENABLED_MASK) == ENABLED
11955                && li.mOnHoverListener.onHover(this, event)) {
11956            return true;
11957        }
11958
11959        return onHoverEvent(event);
11960    }
11961
11962    /**
11963     * Returns true if the view has a child to which it has recently sent
11964     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11965     * it does not have a hovered child, then it must be the innermost hovered view.
11966     * @hide
11967     */
11968    protected boolean hasHoveredChild() {
11969        return false;
11970    }
11971
11972    /**
11973     * Dispatch a generic motion event to the view under the first pointer.
11974     * <p>
11975     * Do not call this method directly.
11976     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11977     * </p>
11978     *
11979     * @param event The motion event to be dispatched.
11980     * @return True if the event was handled by the view, false otherwise.
11981     */
11982    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11983        return false;
11984    }
11985
11986    /**
11987     * Dispatch a generic motion event to the currently focused view.
11988     * <p>
11989     * Do not call this method directly.
11990     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11991     * </p>
11992     *
11993     * @param event The motion event to be dispatched.
11994     * @return True if the event was handled by the view, false otherwise.
11995     */
11996    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11997        return false;
11998    }
11999
12000    /**
12001     * Dispatch a pointer event.
12002     * <p>
12003     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
12004     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
12005     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
12006     * and should not be expected to handle other pointing device features.
12007     * </p>
12008     *
12009     * @param event The motion event to be dispatched.
12010     * @return True if the event was handled by the view, false otherwise.
12011     * @hide
12012     */
12013    public final boolean dispatchPointerEvent(MotionEvent event) {
12014        if (event.isTouchEvent()) {
12015            return dispatchTouchEvent(event);
12016        } else {
12017            return dispatchGenericMotionEvent(event);
12018        }
12019    }
12020
12021    /**
12022     * Called when the window containing this view gains or loses window focus.
12023     * ViewGroups should override to route to their children.
12024     *
12025     * @param hasFocus True if the window containing this view now has focus,
12026     *        false otherwise.
12027     */
12028    public void dispatchWindowFocusChanged(boolean hasFocus) {
12029        onWindowFocusChanged(hasFocus);
12030    }
12031
12032    /**
12033     * Called when the window containing this view gains or loses focus.  Note
12034     * that this is separate from view focus: to receive key events, both
12035     * your view and its window must have focus.  If a window is displayed
12036     * on top of yours that takes input focus, then your own window will lose
12037     * focus but the view focus will remain unchanged.
12038     *
12039     * @param hasWindowFocus True if the window containing this view now has
12040     *        focus, false otherwise.
12041     */
12042    public void onWindowFocusChanged(boolean hasWindowFocus) {
12043        InputMethodManager imm = InputMethodManager.peekInstance();
12044        if (!hasWindowFocus) {
12045            if (isPressed()) {
12046                setPressed(false);
12047            }
12048            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12049            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
12050                imm.focusOut(this);
12051            }
12052            removeLongPressCallback();
12053            removeTapCallback();
12054            onFocusLost();
12055        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
12056            imm.focusIn(this);
12057        }
12058
12059        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
12060
12061        refreshDrawableState();
12062    }
12063
12064    /**
12065     * Returns true if this view is in a window that currently has window focus.
12066     * Note that this is not the same as the view itself having focus.
12067     *
12068     * @return True if this view is in a window that currently has window focus.
12069     */
12070    public boolean hasWindowFocus() {
12071        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
12072    }
12073
12074    /**
12075     * Dispatch a view visibility change down the view hierarchy.
12076     * ViewGroups should override to route to their children.
12077     * @param changedView The view whose visibility changed. Could be 'this' or
12078     * an ancestor view.
12079     * @param visibility The new visibility of changedView: {@link #VISIBLE},
12080     * {@link #INVISIBLE} or {@link #GONE}.
12081     */
12082    protected void dispatchVisibilityChanged(@NonNull View changedView,
12083            @Visibility int visibility) {
12084        onVisibilityChanged(changedView, visibility);
12085    }
12086
12087    /**
12088     * Called when the visibility of the view or an ancestor of the view has
12089     * changed.
12090     *
12091     * @param changedView The view whose visibility changed. May be
12092     *                    {@code this} or an ancestor view.
12093     * @param visibility The new visibility, one of {@link #VISIBLE},
12094     *                   {@link #INVISIBLE} or {@link #GONE}.
12095     */
12096    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
12097    }
12098
12099    /**
12100     * Dispatch a hint about whether this view is displayed. For instance, when
12101     * a View moves out of the screen, it might receives a display hint indicating
12102     * the view is not displayed. Applications should not <em>rely</em> on this hint
12103     * as there is no guarantee that they will receive one.
12104     *
12105     * @param hint A hint about whether or not this view is displayed:
12106     * {@link #VISIBLE} or {@link #INVISIBLE}.
12107     */
12108    public void dispatchDisplayHint(@Visibility int hint) {
12109        onDisplayHint(hint);
12110    }
12111
12112    /**
12113     * Gives this view a hint about whether is displayed or not. For instance, when
12114     * a View moves out of the screen, it might receives a display hint indicating
12115     * the view is not displayed. Applications should not <em>rely</em> on this hint
12116     * as there is no guarantee that they will receive one.
12117     *
12118     * @param hint A hint about whether or not this view is displayed:
12119     * {@link #VISIBLE} or {@link #INVISIBLE}.
12120     */
12121    protected void onDisplayHint(@Visibility int hint) {
12122    }
12123
12124    /**
12125     * Dispatch a window visibility change down the view hierarchy.
12126     * ViewGroups should override to route to their children.
12127     *
12128     * @param visibility The new visibility of the window.
12129     *
12130     * @see #onWindowVisibilityChanged(int)
12131     */
12132    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
12133        onWindowVisibilityChanged(visibility);
12134    }
12135
12136    /**
12137     * Called when the window containing has change its visibility
12138     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
12139     * that this tells you whether or not your window is being made visible
12140     * to the window manager; this does <em>not</em> tell you whether or not
12141     * your window is obscured by other windows on the screen, even if it
12142     * is itself visible.
12143     *
12144     * @param visibility The new visibility of the window.
12145     */
12146    protected void onWindowVisibilityChanged(@Visibility int visibility) {
12147        if (visibility == VISIBLE) {
12148            initialAwakenScrollBars();
12149        }
12150    }
12151
12152    /**
12153     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
12154     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
12155     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
12156     *
12157     * @param isVisible true if this view's visibility to the user is uninterrupted by its
12158     *                  ancestors or by window visibility
12159     * @return true if this view is visible to the user, not counting clipping or overlapping
12160     */
12161    boolean dispatchVisibilityAggregated(boolean isVisible) {
12162        final boolean thisVisible = getVisibility() == VISIBLE;
12163        // If we're not visible but something is telling us we are, ignore it.
12164        if (thisVisible || !isVisible) {
12165            onVisibilityAggregated(isVisible);
12166        }
12167        return thisVisible && isVisible;
12168    }
12169
12170    /**
12171     * Called when the user-visibility of this View is potentially affected by a change
12172     * to this view itself, an ancestor view or the window this view is attached to.
12173     *
12174     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
12175     *                  and this view's window is also visible
12176     */
12177    @CallSuper
12178    public void onVisibilityAggregated(boolean isVisible) {
12179        if (isVisible && mAttachInfo != null) {
12180            initialAwakenScrollBars();
12181        }
12182
12183        final Drawable dr = mBackground;
12184        if (dr != null && isVisible != dr.isVisible()) {
12185            dr.setVisible(isVisible, false);
12186        }
12187        final Drawable hl = mDefaultFocusHighlight;
12188        if (hl != null && isVisible != hl.isVisible()) {
12189            hl.setVisible(isVisible, false);
12190        }
12191        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
12192        if (fg != null && isVisible != fg.isVisible()) {
12193            fg.setVisible(isVisible, false);
12194        }
12195
12196        if (isAutofillable()) {
12197            AutofillManager afm = getAutofillManager();
12198
12199            if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
12200                if (mVisibilityChangeForAutofillHandler != null) {
12201                    mVisibilityChangeForAutofillHandler.removeMessages(0);
12202                }
12203
12204                // If the view is in the background but still part of the hierarchy this is called
12205                // with isVisible=false. Hence visibility==false requires further checks
12206                if (isVisible) {
12207                    afm.notifyViewVisibilityChanged(this, true);
12208                } else {
12209                    if (mVisibilityChangeForAutofillHandler == null) {
12210                        mVisibilityChangeForAutofillHandler =
12211                                new VisibilityChangeForAutofillHandler(afm, this);
12212                    }
12213                    // Let current operation (e.g. removal of the view from the hierarchy)
12214                    // finish before checking state
12215                    mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
12216                }
12217            }
12218        }
12219    }
12220
12221    /**
12222     * Returns the current visibility of the window this view is attached to
12223     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
12224     *
12225     * @return Returns the current visibility of the view's window.
12226     */
12227    @Visibility
12228    public int getWindowVisibility() {
12229        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
12230    }
12231
12232    /**
12233     * Retrieve the overall visible display size in which the window this view is
12234     * attached to has been positioned in.  This takes into account screen
12235     * decorations above the window, for both cases where the window itself
12236     * is being position inside of them or the window is being placed under
12237     * then and covered insets are used for the window to position its content
12238     * inside.  In effect, this tells you the available area where content can
12239     * be placed and remain visible to users.
12240     *
12241     * <p>This function requires an IPC back to the window manager to retrieve
12242     * the requested information, so should not be used in performance critical
12243     * code like drawing.
12244     *
12245     * @param outRect Filled in with the visible display frame.  If the view
12246     * is not attached to a window, this is simply the raw display size.
12247     */
12248    public void getWindowVisibleDisplayFrame(Rect outRect) {
12249        if (mAttachInfo != null) {
12250            try {
12251                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12252            } catch (RemoteException e) {
12253                return;
12254            }
12255            // XXX This is really broken, and probably all needs to be done
12256            // in the window manager, and we need to know more about whether
12257            // we want the area behind or in front of the IME.
12258            final Rect insets = mAttachInfo.mVisibleInsets;
12259            outRect.left += insets.left;
12260            outRect.top += insets.top;
12261            outRect.right -= insets.right;
12262            outRect.bottom -= insets.bottom;
12263            return;
12264        }
12265        // The view is not attached to a display so we don't have a context.
12266        // Make a best guess about the display size.
12267        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12268        d.getRectSize(outRect);
12269    }
12270
12271    /**
12272     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
12273     * is currently in without any insets.
12274     *
12275     * @hide
12276     */
12277    public void getWindowDisplayFrame(Rect outRect) {
12278        if (mAttachInfo != null) {
12279            try {
12280                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12281            } catch (RemoteException e) {
12282                return;
12283            }
12284            return;
12285        }
12286        // The view is not attached to a display so we don't have a context.
12287        // Make a best guess about the display size.
12288        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12289        d.getRectSize(outRect);
12290    }
12291
12292    /**
12293     * Dispatch a notification about a resource configuration change down
12294     * the view hierarchy.
12295     * ViewGroups should override to route to their children.
12296     *
12297     * @param newConfig The new resource configuration.
12298     *
12299     * @see #onConfigurationChanged(android.content.res.Configuration)
12300     */
12301    public void dispatchConfigurationChanged(Configuration newConfig) {
12302        onConfigurationChanged(newConfig);
12303    }
12304
12305    /**
12306     * Called when the current configuration of the resources being used
12307     * by the application have changed.  You can use this to decide when
12308     * to reload resources that can changed based on orientation and other
12309     * configuration characteristics.  You only need to use this if you are
12310     * not relying on the normal {@link android.app.Activity} mechanism of
12311     * recreating the activity instance upon a configuration change.
12312     *
12313     * @param newConfig The new resource configuration.
12314     */
12315    protected void onConfigurationChanged(Configuration newConfig) {
12316    }
12317
12318    /**
12319     * Private function to aggregate all per-view attributes in to the view
12320     * root.
12321     */
12322    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12323        performCollectViewAttributes(attachInfo, visibility);
12324    }
12325
12326    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12327        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
12328            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
12329                attachInfo.mKeepScreenOn = true;
12330            }
12331            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
12332            ListenerInfo li = mListenerInfo;
12333            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
12334                attachInfo.mHasSystemUiListeners = true;
12335            }
12336        }
12337    }
12338
12339    void needGlobalAttributesUpdate(boolean force) {
12340        final AttachInfo ai = mAttachInfo;
12341        if (ai != null && !ai.mRecomputeGlobalAttributes) {
12342            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
12343                    || ai.mHasSystemUiListeners) {
12344                ai.mRecomputeGlobalAttributes = true;
12345            }
12346        }
12347    }
12348
12349    /**
12350     * Returns whether the device is currently in touch mode.  Touch mode is entered
12351     * once the user begins interacting with the device by touch, and affects various
12352     * things like whether focus is always visible to the user.
12353     *
12354     * @return Whether the device is in touch mode.
12355     */
12356    @ViewDebug.ExportedProperty
12357    public boolean isInTouchMode() {
12358        if (mAttachInfo != null) {
12359            return mAttachInfo.mInTouchMode;
12360        } else {
12361            return ViewRootImpl.isInTouchMode();
12362        }
12363    }
12364
12365    /**
12366     * Returns the context the view is running in, through which it can
12367     * access the current theme, resources, etc.
12368     *
12369     * @return The view's Context.
12370     */
12371    @ViewDebug.CapturedViewProperty
12372    public final Context getContext() {
12373        return mContext;
12374    }
12375
12376    /**
12377     * Handle a key event before it is processed by any input method
12378     * associated with the view hierarchy.  This can be used to intercept
12379     * key events in special situations before the IME consumes them; a
12380     * typical example would be handling the BACK key to update the application's
12381     * UI instead of allowing the IME to see it and close itself.
12382     *
12383     * @param keyCode The value in event.getKeyCode().
12384     * @param event Description of the key event.
12385     * @return If you handled the event, return true. If you want to allow the
12386     *         event to be handled by the next receiver, return false.
12387     */
12388    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
12389        return false;
12390    }
12391
12392    /**
12393     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
12394     * KeyEvent.Callback.onKeyDown()}: perform press of the view
12395     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
12396     * is released, if the view is enabled and clickable.
12397     * <p>
12398     * Key presses in software keyboards will generally NOT trigger this
12399     * listener, although some may elect to do so in some situations. Do not
12400     * rely on this to catch software key presses.
12401     *
12402     * @param keyCode a key code that represents the button pressed, from
12403     *                {@link android.view.KeyEvent}
12404     * @param event the KeyEvent object that defines the button action
12405     */
12406    public boolean onKeyDown(int keyCode, KeyEvent event) {
12407        if (KeyEvent.isConfirmKey(keyCode)) {
12408            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12409                return true;
12410            }
12411
12412            if (event.getRepeatCount() == 0) {
12413                // Long clickable items don't necessarily have to be clickable.
12414                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
12415                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
12416                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
12417                    // For the purposes of menu anchoring and drawable hotspots,
12418                    // key events are considered to be at the center of the view.
12419                    final float x = getWidth() / 2f;
12420                    final float y = getHeight() / 2f;
12421                    if (clickable) {
12422                        setPressed(true, x, y);
12423                    }
12424                    checkForLongClick(0, x, y);
12425                    return true;
12426                }
12427            }
12428        }
12429
12430        return false;
12431    }
12432
12433    /**
12434     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
12435     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
12436     * the event).
12437     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12438     * although some may elect to do so in some situations. Do not rely on this to
12439     * catch software key presses.
12440     */
12441    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
12442        return false;
12443    }
12444
12445    /**
12446     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
12447     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
12448     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
12449     * or {@link KeyEvent#KEYCODE_SPACE} is released.
12450     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12451     * although some may elect to do so in some situations. Do not rely on this to
12452     * catch software key presses.
12453     *
12454     * @param keyCode A key code that represents the button pressed, from
12455     *                {@link android.view.KeyEvent}.
12456     * @param event   The KeyEvent object that defines the button action.
12457     */
12458    public boolean onKeyUp(int keyCode, KeyEvent event) {
12459        if (KeyEvent.isConfirmKey(keyCode)) {
12460            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12461                return true;
12462            }
12463            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
12464                setPressed(false);
12465
12466                if (!mHasPerformedLongPress) {
12467                    // This is a tap, so remove the longpress check
12468                    removeLongPressCallback();
12469                    if (!event.isCanceled()) {
12470                        return performClick();
12471                    }
12472                }
12473            }
12474        }
12475        return false;
12476    }
12477
12478    /**
12479     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
12480     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
12481     * the event).
12482     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12483     * although some may elect to do so in some situations. Do not rely on this to
12484     * catch software key presses.
12485     *
12486     * @param keyCode     A key code that represents the button pressed, from
12487     *                    {@link android.view.KeyEvent}.
12488     * @param repeatCount The number of times the action was made.
12489     * @param event       The KeyEvent object that defines the button action.
12490     */
12491    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
12492        return false;
12493    }
12494
12495    /**
12496     * Called on the focused view when a key shortcut event is not handled.
12497     * Override this method to implement local key shortcuts for the View.
12498     * Key shortcuts can also be implemented by setting the
12499     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
12500     *
12501     * @param keyCode The value in event.getKeyCode().
12502     * @param event Description of the key event.
12503     * @return If you handled the event, return true. If you want to allow the
12504     *         event to be handled by the next receiver, return false.
12505     */
12506    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
12507        return false;
12508    }
12509
12510    /**
12511     * Check whether the called view is a text editor, in which case it
12512     * would make sense to automatically display a soft input window for
12513     * it.  Subclasses should override this if they implement
12514     * {@link #onCreateInputConnection(EditorInfo)} to return true if
12515     * a call on that method would return a non-null InputConnection, and
12516     * they are really a first-class editor that the user would normally
12517     * start typing on when the go into a window containing your view.
12518     *
12519     * <p>The default implementation always returns false.  This does
12520     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
12521     * will not be called or the user can not otherwise perform edits on your
12522     * view; it is just a hint to the system that this is not the primary
12523     * purpose of this view.
12524     *
12525     * @return Returns true if this view is a text editor, else false.
12526     */
12527    public boolean onCheckIsTextEditor() {
12528        return false;
12529    }
12530
12531    /**
12532     * Create a new InputConnection for an InputMethod to interact
12533     * with the view.  The default implementation returns null, since it doesn't
12534     * support input methods.  You can override this to implement such support.
12535     * This is only needed for views that take focus and text input.
12536     *
12537     * <p>When implementing this, you probably also want to implement
12538     * {@link #onCheckIsTextEditor()} to indicate you will return a
12539     * non-null InputConnection.</p>
12540     *
12541     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12542     * object correctly and in its entirety, so that the connected IME can rely
12543     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12544     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12545     * must be filled in with the correct cursor position for IMEs to work correctly
12546     * with your application.</p>
12547     *
12548     * @param outAttrs Fill in with attribute information about the connection.
12549     */
12550    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12551        return null;
12552    }
12553
12554    /**
12555     * Called by the {@link android.view.inputmethod.InputMethodManager}
12556     * when a view who is not the current
12557     * input connection target is trying to make a call on the manager.  The
12558     * default implementation returns false; you can override this to return
12559     * true for certain views if you are performing InputConnection proxying
12560     * to them.
12561     * @param view The View that is making the InputMethodManager call.
12562     * @return Return true to allow the call, false to reject.
12563     */
12564    public boolean checkInputConnectionProxy(View view) {
12565        return false;
12566    }
12567
12568    /**
12569     * Show the context menu for this view. It is not safe to hold on to the
12570     * menu after returning from this method.
12571     *
12572     * You should normally not overload this method. Overload
12573     * {@link #onCreateContextMenu(ContextMenu)} or define an
12574     * {@link OnCreateContextMenuListener} to add items to the context menu.
12575     *
12576     * @param menu The context menu to populate
12577     */
12578    public void createContextMenu(ContextMenu menu) {
12579        ContextMenuInfo menuInfo = getContextMenuInfo();
12580
12581        // Sets the current menu info so all items added to menu will have
12582        // my extra info set.
12583        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12584
12585        onCreateContextMenu(menu);
12586        ListenerInfo li = mListenerInfo;
12587        if (li != null && li.mOnCreateContextMenuListener != null) {
12588            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12589        }
12590
12591        // Clear the extra information so subsequent items that aren't mine don't
12592        // have my extra info.
12593        ((MenuBuilder)menu).setCurrentMenuInfo(null);
12594
12595        if (mParent != null) {
12596            mParent.createContextMenu(menu);
12597        }
12598    }
12599
12600    /**
12601     * Views should implement this if they have extra information to associate
12602     * with the context menu. The return result is supplied as a parameter to
12603     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12604     * callback.
12605     *
12606     * @return Extra information about the item for which the context menu
12607     *         should be shown. This information will vary across different
12608     *         subclasses of View.
12609     */
12610    protected ContextMenuInfo getContextMenuInfo() {
12611        return null;
12612    }
12613
12614    /**
12615     * Views should implement this if the view itself is going to add items to
12616     * the context menu.
12617     *
12618     * @param menu the context menu to populate
12619     */
12620    protected void onCreateContextMenu(ContextMenu menu) {
12621    }
12622
12623    /**
12624     * Implement this method to handle trackball motion events.  The
12625     * <em>relative</em> movement of the trackball since the last event
12626     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12627     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12628     * that a movement of 1 corresponds to the user pressing one DPAD key (so
12629     * they will often be fractional values, representing the more fine-grained
12630     * movement information available from a trackball).
12631     *
12632     * @param event The motion event.
12633     * @return True if the event was handled, false otherwise.
12634     */
12635    public boolean onTrackballEvent(MotionEvent event) {
12636        return false;
12637    }
12638
12639    /**
12640     * Implement this method to handle generic motion events.
12641     * <p>
12642     * Generic motion events describe joystick movements, mouse hovers, track pad
12643     * touches, scroll wheel movements and other input events.  The
12644     * {@link MotionEvent#getSource() source} of the motion event specifies
12645     * the class of input that was received.  Implementations of this method
12646     * must examine the bits in the source before processing the event.
12647     * The following code example shows how this is done.
12648     * </p><p>
12649     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12650     * are delivered to the view under the pointer.  All other generic motion events are
12651     * delivered to the focused view.
12652     * </p>
12653     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12654     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12655     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12656     *             // process the joystick movement...
12657     *             return true;
12658     *         }
12659     *     }
12660     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12661     *         switch (event.getAction()) {
12662     *             case MotionEvent.ACTION_HOVER_MOVE:
12663     *                 // process the mouse hover movement...
12664     *                 return true;
12665     *             case MotionEvent.ACTION_SCROLL:
12666     *                 // process the scroll wheel movement...
12667     *                 return true;
12668     *         }
12669     *     }
12670     *     return super.onGenericMotionEvent(event);
12671     * }</pre>
12672     *
12673     * @param event The generic motion event being processed.
12674     * @return True if the event was handled, false otherwise.
12675     */
12676    public boolean onGenericMotionEvent(MotionEvent event) {
12677        return false;
12678    }
12679
12680    /**
12681     * Implement this method to handle hover events.
12682     * <p>
12683     * This method is called whenever a pointer is hovering into, over, or out of the
12684     * bounds of a view and the view is not currently being touched.
12685     * Hover events are represented as pointer events with action
12686     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12687     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12688     * </p>
12689     * <ul>
12690     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12691     * when the pointer enters the bounds of the view.</li>
12692     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12693     * when the pointer has already entered the bounds of the view and has moved.</li>
12694     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12695     * when the pointer has exited the bounds of the view or when the pointer is
12696     * about to go down due to a button click, tap, or similar user action that
12697     * causes the view to be touched.</li>
12698     * </ul>
12699     * <p>
12700     * The view should implement this method to return true to indicate that it is
12701     * handling the hover event, such as by changing its drawable state.
12702     * </p><p>
12703     * The default implementation calls {@link #setHovered} to update the hovered state
12704     * of the view when a hover enter or hover exit event is received, if the view
12705     * is enabled and is clickable.  The default implementation also sends hover
12706     * accessibility events.
12707     * </p>
12708     *
12709     * @param event The motion event that describes the hover.
12710     * @return True if the view handled the hover event.
12711     *
12712     * @see #isHovered
12713     * @see #setHovered
12714     * @see #onHoverChanged
12715     */
12716    public boolean onHoverEvent(MotionEvent event) {
12717        // The root view may receive hover (or touch) events that are outside the bounds of
12718        // the window.  This code ensures that we only send accessibility events for
12719        // hovers that are actually within the bounds of the root view.
12720        final int action = event.getActionMasked();
12721        if (!mSendingHoverAccessibilityEvents) {
12722            if ((action == MotionEvent.ACTION_HOVER_ENTER
12723                    || action == MotionEvent.ACTION_HOVER_MOVE)
12724                    && !hasHoveredChild()
12725                    && pointInView(event.getX(), event.getY())) {
12726                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12727                mSendingHoverAccessibilityEvents = true;
12728            }
12729        } else {
12730            if (action == MotionEvent.ACTION_HOVER_EXIT
12731                    || (action == MotionEvent.ACTION_MOVE
12732                            && !pointInView(event.getX(), event.getY()))) {
12733                mSendingHoverAccessibilityEvents = false;
12734                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12735            }
12736        }
12737
12738        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12739                && event.isFromSource(InputDevice.SOURCE_MOUSE)
12740                && isOnScrollbar(event.getX(), event.getY())) {
12741            awakenScrollBars();
12742        }
12743
12744        // If we consider ourself hoverable, or if we we're already hovered,
12745        // handle changing state in response to ENTER and EXIT events.
12746        if (isHoverable() || isHovered()) {
12747            switch (action) {
12748                case MotionEvent.ACTION_HOVER_ENTER:
12749                    setHovered(true);
12750                    break;
12751                case MotionEvent.ACTION_HOVER_EXIT:
12752                    setHovered(false);
12753                    break;
12754            }
12755
12756            // Dispatch the event to onGenericMotionEvent before returning true.
12757            // This is to provide compatibility with existing applications that
12758            // handled HOVER_MOVE events in onGenericMotionEvent and that would
12759            // break because of the new default handling for hoverable views
12760            // in onHoverEvent.
12761            // Note that onGenericMotionEvent will be called by default when
12762            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12763            dispatchGenericMotionEventInternal(event);
12764            // The event was already handled by calling setHovered(), so always
12765            // return true.
12766            return true;
12767        }
12768
12769        return false;
12770    }
12771
12772    /**
12773     * Returns true if the view should handle {@link #onHoverEvent}
12774     * by calling {@link #setHovered} to change its hovered state.
12775     *
12776     * @return True if the view is hoverable.
12777     */
12778    private boolean isHoverable() {
12779        final int viewFlags = mViewFlags;
12780        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12781            return false;
12782        }
12783
12784        return (viewFlags & CLICKABLE) == CLICKABLE
12785                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12786                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12787    }
12788
12789    /**
12790     * Returns true if the view is currently hovered.
12791     *
12792     * @return True if the view is currently hovered.
12793     *
12794     * @see #setHovered
12795     * @see #onHoverChanged
12796     */
12797    @ViewDebug.ExportedProperty
12798    public boolean isHovered() {
12799        return (mPrivateFlags & PFLAG_HOVERED) != 0;
12800    }
12801
12802    /**
12803     * Sets whether the view is currently hovered.
12804     * <p>
12805     * Calling this method also changes the drawable state of the view.  This
12806     * enables the view to react to hover by using different drawable resources
12807     * to change its appearance.
12808     * </p><p>
12809     * The {@link #onHoverChanged} method is called when the hovered state changes.
12810     * </p>
12811     *
12812     * @param hovered True if the view is hovered.
12813     *
12814     * @see #isHovered
12815     * @see #onHoverChanged
12816     */
12817    public void setHovered(boolean hovered) {
12818        if (hovered) {
12819            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12820                mPrivateFlags |= PFLAG_HOVERED;
12821                refreshDrawableState();
12822                onHoverChanged(true);
12823            }
12824        } else {
12825            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12826                mPrivateFlags &= ~PFLAG_HOVERED;
12827                refreshDrawableState();
12828                onHoverChanged(false);
12829            }
12830        }
12831    }
12832
12833    /**
12834     * Implement this method to handle hover state changes.
12835     * <p>
12836     * This method is called whenever the hover state changes as a result of a
12837     * call to {@link #setHovered}.
12838     * </p>
12839     *
12840     * @param hovered The current hover state, as returned by {@link #isHovered}.
12841     *
12842     * @see #isHovered
12843     * @see #setHovered
12844     */
12845    public void onHoverChanged(boolean hovered) {
12846    }
12847
12848    /**
12849     * Handles scroll bar dragging by mouse input.
12850     *
12851     * @hide
12852     * @param event The motion event.
12853     *
12854     * @return true if the event was handled as a scroll bar dragging, false otherwise.
12855     */
12856    protected boolean handleScrollBarDragging(MotionEvent event) {
12857        if (mScrollCache == null) {
12858            return false;
12859        }
12860        final float x = event.getX();
12861        final float y = event.getY();
12862        final int action = event.getAction();
12863        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12864                && action != MotionEvent.ACTION_DOWN)
12865                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12866                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12867            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12868            return false;
12869        }
12870
12871        switch (action) {
12872            case MotionEvent.ACTION_MOVE:
12873                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12874                    return false;
12875                }
12876                if (mScrollCache.mScrollBarDraggingState
12877                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12878                    final Rect bounds = mScrollCache.mScrollBarBounds;
12879                    getVerticalScrollBarBounds(bounds, null);
12880                    final int range = computeVerticalScrollRange();
12881                    final int offset = computeVerticalScrollOffset();
12882                    final int extent = computeVerticalScrollExtent();
12883
12884                    final int thumbLength = ScrollBarUtils.getThumbLength(
12885                            bounds.height(), bounds.width(), extent, range);
12886                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12887                            bounds.height(), thumbLength, extent, range, offset);
12888
12889                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
12890                    final float maxThumbOffset = bounds.height() - thumbLength;
12891                    final float newThumbOffset =
12892                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12893                    final int height = getHeight();
12894                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12895                            && height > 0 && extent > 0) {
12896                        final int newY = Math.round((range - extent)
12897                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12898                        if (newY != getScrollY()) {
12899                            mScrollCache.mScrollBarDraggingPos = y;
12900                            setScrollY(newY);
12901                        }
12902                    }
12903                    return true;
12904                }
12905                if (mScrollCache.mScrollBarDraggingState
12906                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12907                    final Rect bounds = mScrollCache.mScrollBarBounds;
12908                    getHorizontalScrollBarBounds(bounds, null);
12909                    final int range = computeHorizontalScrollRange();
12910                    final int offset = computeHorizontalScrollOffset();
12911                    final int extent = computeHorizontalScrollExtent();
12912
12913                    final int thumbLength = ScrollBarUtils.getThumbLength(
12914                            bounds.width(), bounds.height(), extent, range);
12915                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12916                            bounds.width(), thumbLength, extent, range, offset);
12917
12918                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
12919                    final float maxThumbOffset = bounds.width() - thumbLength;
12920                    final float newThumbOffset =
12921                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12922                    final int width = getWidth();
12923                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12924                            && width > 0 && extent > 0) {
12925                        final int newX = Math.round((range - extent)
12926                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12927                        if (newX != getScrollX()) {
12928                            mScrollCache.mScrollBarDraggingPos = x;
12929                            setScrollX(newX);
12930                        }
12931                    }
12932                    return true;
12933                }
12934            case MotionEvent.ACTION_DOWN:
12935                if (mScrollCache.state == ScrollabilityCache.OFF) {
12936                    return false;
12937                }
12938                if (isOnVerticalScrollbarThumb(x, y)) {
12939                    mScrollCache.mScrollBarDraggingState =
12940                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12941                    mScrollCache.mScrollBarDraggingPos = y;
12942                    return true;
12943                }
12944                if (isOnHorizontalScrollbarThumb(x, y)) {
12945                    mScrollCache.mScrollBarDraggingState =
12946                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12947                    mScrollCache.mScrollBarDraggingPos = x;
12948                    return true;
12949                }
12950        }
12951        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12952        return false;
12953    }
12954
12955    /**
12956     * Implement this method to handle touch screen motion events.
12957     * <p>
12958     * If this method is used to detect click actions, it is recommended that
12959     * the actions be performed by implementing and calling
12960     * {@link #performClick()}. This will ensure consistent system behavior,
12961     * including:
12962     * <ul>
12963     * <li>obeying click sound preferences
12964     * <li>dispatching OnClickListener calls
12965     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12966     * accessibility features are enabled
12967     * </ul>
12968     *
12969     * @param event The motion event.
12970     * @return True if the event was handled, false otherwise.
12971     */
12972    public boolean onTouchEvent(MotionEvent event) {
12973        final float x = event.getX();
12974        final float y = event.getY();
12975        final int viewFlags = mViewFlags;
12976        final int action = event.getAction();
12977
12978        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12979                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12980                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12981
12982        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12983            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12984                setPressed(false);
12985            }
12986            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12987            // A disabled view that is clickable still consumes the touch
12988            // events, it just doesn't respond to them.
12989            return clickable;
12990        }
12991        if (mTouchDelegate != null) {
12992            if (mTouchDelegate.onTouchEvent(event)) {
12993                return true;
12994            }
12995        }
12996
12997        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12998            switch (action) {
12999                case MotionEvent.ACTION_UP:
13000                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13001                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
13002                        handleTooltipUp();
13003                    }
13004                    if (!clickable) {
13005                        removeTapCallback();
13006                        removeLongPressCallback();
13007                        mInContextButtonPress = false;
13008                        mHasPerformedLongPress = false;
13009                        mIgnoreNextUpEvent = false;
13010                        break;
13011                    }
13012                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
13013                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
13014                        // take focus if we don't have it already and we should in
13015                        // touch mode.
13016                        boolean focusTaken = false;
13017                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
13018                            focusTaken = requestFocus();
13019                        }
13020
13021                        if (prepressed) {
13022                            // The button is being released before we actually
13023                            // showed it as pressed.  Make it show the pressed
13024                            // state now (before scheduling the click) to ensure
13025                            // the user sees it.
13026                            setPressed(true, x, y);
13027                        }
13028
13029                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
13030                            // This is a tap, so remove the longpress check
13031                            removeLongPressCallback();
13032
13033                            // Only perform take click actions if we were in the pressed state
13034                            if (!focusTaken) {
13035                                // Use a Runnable and post this rather than calling
13036                                // performClick directly. This lets other visual state
13037                                // of the view update before click actions start.
13038                                if (mPerformClick == null) {
13039                                    mPerformClick = new PerformClick();
13040                                }
13041                                if (!post(mPerformClick)) {
13042                                    performClick();
13043                                }
13044                            }
13045                        }
13046
13047                        if (mUnsetPressedState == null) {
13048                            mUnsetPressedState = new UnsetPressedState();
13049                        }
13050
13051                        if (prepressed) {
13052                            postDelayed(mUnsetPressedState,
13053                                    ViewConfiguration.getPressedStateDuration());
13054                        } else if (!post(mUnsetPressedState)) {
13055                            // If the post failed, unpress right now
13056                            mUnsetPressedState.run();
13057                        }
13058
13059                        removeTapCallback();
13060                    }
13061                    mIgnoreNextUpEvent = false;
13062                    break;
13063
13064                case MotionEvent.ACTION_DOWN:
13065                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
13066                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
13067                    }
13068                    mHasPerformedLongPress = false;
13069
13070                    if (!clickable) {
13071                        checkForLongClick(0, x, y);
13072                        break;
13073                    }
13074
13075                    if (performButtonActionOnTouchDown(event)) {
13076                        break;
13077                    }
13078
13079                    // Walk up the hierarchy to determine if we're inside a scrolling container.
13080                    boolean isInScrollingContainer = isInScrollingContainer();
13081
13082                    // For views inside a scrolling container, delay the pressed feedback for
13083                    // a short period in case this is a scroll.
13084                    if (isInScrollingContainer) {
13085                        mPrivateFlags |= PFLAG_PREPRESSED;
13086                        if (mPendingCheckForTap == null) {
13087                            mPendingCheckForTap = new CheckForTap();
13088                        }
13089                        mPendingCheckForTap.x = event.getX();
13090                        mPendingCheckForTap.y = event.getY();
13091                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
13092                    } else {
13093                        // Not inside a scrolling container, so show the feedback right away
13094                        setPressed(true, x, y);
13095                        checkForLongClick(0, x, y);
13096                    }
13097                    break;
13098
13099                case MotionEvent.ACTION_CANCEL:
13100                    if (clickable) {
13101                        setPressed(false);
13102                    }
13103                    removeTapCallback();
13104                    removeLongPressCallback();
13105                    mInContextButtonPress = false;
13106                    mHasPerformedLongPress = false;
13107                    mIgnoreNextUpEvent = false;
13108                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13109                    break;
13110
13111                case MotionEvent.ACTION_MOVE:
13112                    if (clickable) {
13113                        drawableHotspotChanged(x, y);
13114                    }
13115
13116                    // Be lenient about moving outside of buttons
13117                    if (!pointInView(x, y, mTouchSlop)) {
13118                        // Outside button
13119                        // Remove any future long press/tap checks
13120                        removeTapCallback();
13121                        removeLongPressCallback();
13122                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
13123                            setPressed(false);
13124                        }
13125                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13126                    }
13127                    break;
13128            }
13129
13130            return true;
13131        }
13132
13133        return false;
13134    }
13135
13136    /**
13137     * @hide
13138     */
13139    public boolean isInScrollingContainer() {
13140        ViewParent p = getParent();
13141        while (p != null && p instanceof ViewGroup) {
13142            if (((ViewGroup) p).shouldDelayChildPressedState()) {
13143                return true;
13144            }
13145            p = p.getParent();
13146        }
13147        return false;
13148    }
13149
13150    /**
13151     * Remove the longpress detection timer.
13152     */
13153    private void removeLongPressCallback() {
13154        if (mPendingCheckForLongPress != null) {
13155            removeCallbacks(mPendingCheckForLongPress);
13156        }
13157    }
13158
13159    /**
13160     * Remove the pending click action
13161     */
13162    private void removePerformClickCallback() {
13163        if (mPerformClick != null) {
13164            removeCallbacks(mPerformClick);
13165        }
13166    }
13167
13168    /**
13169     * Remove the prepress detection timer.
13170     */
13171    private void removeUnsetPressCallback() {
13172        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
13173            setPressed(false);
13174            removeCallbacks(mUnsetPressedState);
13175        }
13176    }
13177
13178    /**
13179     * Remove the tap detection timer.
13180     */
13181    private void removeTapCallback() {
13182        if (mPendingCheckForTap != null) {
13183            mPrivateFlags &= ~PFLAG_PREPRESSED;
13184            removeCallbacks(mPendingCheckForTap);
13185        }
13186    }
13187
13188    /**
13189     * Cancels a pending long press.  Your subclass can use this if you
13190     * want the context menu to come up if the user presses and holds
13191     * at the same place, but you don't want it to come up if they press
13192     * and then move around enough to cause scrolling.
13193     */
13194    public void cancelLongPress() {
13195        removeLongPressCallback();
13196
13197        /*
13198         * The prepressed state handled by the tap callback is a display
13199         * construct, but the tap callback will post a long press callback
13200         * less its own timeout. Remove it here.
13201         */
13202        removeTapCallback();
13203    }
13204
13205    /**
13206     * Remove the pending callback for sending a
13207     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
13208     */
13209    private void removeSendViewScrolledAccessibilityEventCallback() {
13210        if (mSendViewScrolledAccessibilityEvent != null) {
13211            removeCallbacks(mSendViewScrolledAccessibilityEvent);
13212            mSendViewScrolledAccessibilityEvent.mIsPending = false;
13213        }
13214    }
13215
13216    /**
13217     * Sets the TouchDelegate for this View.
13218     */
13219    public void setTouchDelegate(TouchDelegate delegate) {
13220        mTouchDelegate = delegate;
13221    }
13222
13223    /**
13224     * Gets the TouchDelegate for this View.
13225     */
13226    public TouchDelegate getTouchDelegate() {
13227        return mTouchDelegate;
13228    }
13229
13230    /**
13231     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
13232     *
13233     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
13234     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
13235     * available. This method should only be called for touch events.
13236     *
13237     * <p class="note">This api is not intended for most applications. Buffered dispatch
13238     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
13239     * streams will not improve your input latency. Side effects include: increased latency,
13240     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
13241     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
13242     * you.</p>
13243     */
13244    public final void requestUnbufferedDispatch(MotionEvent event) {
13245        final int action = event.getAction();
13246        if (mAttachInfo == null
13247                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
13248                || !event.isTouchEvent()) {
13249            return;
13250        }
13251        mAttachInfo.mUnbufferedDispatchRequested = true;
13252    }
13253
13254    /**
13255     * Set flags controlling behavior of this view.
13256     *
13257     * @param flags Constant indicating the value which should be set
13258     * @param mask Constant indicating the bit range that should be changed
13259     */
13260    void setFlags(int flags, int mask) {
13261        final boolean accessibilityEnabled =
13262                AccessibilityManager.getInstance(mContext).isEnabled();
13263        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
13264
13265        int old = mViewFlags;
13266        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
13267
13268        int changed = mViewFlags ^ old;
13269        if (changed == 0) {
13270            return;
13271        }
13272        int privateFlags = mPrivateFlags;
13273
13274        // If focusable is auto, update the FOCUSABLE bit.
13275        int focusableChangedByAuto = 0;
13276        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
13277                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
13278            // Heuristic only takes into account whether view is clickable.
13279            final int newFocus;
13280            if ((mViewFlags & CLICKABLE) != 0) {
13281                newFocus = FOCUSABLE;
13282            } else {
13283                newFocus = NOT_FOCUSABLE;
13284            }
13285            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
13286            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
13287            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
13288        }
13289
13290        /* Check if the FOCUSABLE bit has changed */
13291        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
13292            if (((old & FOCUSABLE) == FOCUSABLE)
13293                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
13294                /* Give up focus if we are no longer focusable */
13295                clearFocus();
13296                if (mParent instanceof ViewGroup) {
13297                    ((ViewGroup) mParent).clearFocusedInCluster();
13298                }
13299            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
13300                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
13301                /*
13302                 * Tell the view system that we are now available to take focus
13303                 * if no one else already has it.
13304                 */
13305                if (mParent != null) {
13306                    ViewRootImpl viewRootImpl = getViewRootImpl();
13307                    if (!sAutoFocusableOffUIThreadWontNotifyParents
13308                            || focusableChangedByAuto == 0
13309                            || viewRootImpl == null
13310                            || viewRootImpl.mThread == Thread.currentThread()) {
13311                        mParent.focusableViewAvailable(this);
13312                    }
13313                }
13314            }
13315        }
13316
13317        final int newVisibility = flags & VISIBILITY_MASK;
13318        if (newVisibility == VISIBLE) {
13319            if ((changed & VISIBILITY_MASK) != 0) {
13320                /*
13321                 * If this view is becoming visible, invalidate it in case it changed while
13322                 * it was not visible. Marking it drawn ensures that the invalidation will
13323                 * go through.
13324                 */
13325                mPrivateFlags |= PFLAG_DRAWN;
13326                invalidate(true);
13327
13328                needGlobalAttributesUpdate(true);
13329
13330                // a view becoming visible is worth notifying the parent
13331                // about in case nothing has focus.  even if this specific view
13332                // isn't focusable, it may contain something that is, so let
13333                // the root view try to give this focus if nothing else does.
13334                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
13335                    mParent.focusableViewAvailable(this);
13336                }
13337            }
13338        }
13339
13340        /* Check if the GONE bit has changed */
13341        if ((changed & GONE) != 0) {
13342            needGlobalAttributesUpdate(false);
13343            requestLayout();
13344
13345            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
13346                if (hasFocus()) {
13347                    clearFocus();
13348                    if (mParent instanceof ViewGroup) {
13349                        ((ViewGroup) mParent).clearFocusedInCluster();
13350                    }
13351                }
13352                clearAccessibilityFocus();
13353                destroyDrawingCache();
13354                if (mParent instanceof View) {
13355                    // GONE views noop invalidation, so invalidate the parent
13356                    ((View) mParent).invalidate(true);
13357                }
13358                // Mark the view drawn to ensure that it gets invalidated properly the next
13359                // time it is visible and gets invalidated
13360                mPrivateFlags |= PFLAG_DRAWN;
13361            }
13362            if (mAttachInfo != null) {
13363                mAttachInfo.mViewVisibilityChanged = true;
13364            }
13365        }
13366
13367        /* Check if the VISIBLE bit has changed */
13368        if ((changed & INVISIBLE) != 0) {
13369            needGlobalAttributesUpdate(false);
13370            /*
13371             * If this view is becoming invisible, set the DRAWN flag so that
13372             * the next invalidate() will not be skipped.
13373             */
13374            mPrivateFlags |= PFLAG_DRAWN;
13375
13376            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
13377                // root view becoming invisible shouldn't clear focus and accessibility focus
13378                if (getRootView() != this) {
13379                    if (hasFocus()) {
13380                        clearFocus();
13381                        if (mParent instanceof ViewGroup) {
13382                            ((ViewGroup) mParent).clearFocusedInCluster();
13383                        }
13384                    }
13385                    clearAccessibilityFocus();
13386                }
13387            }
13388            if (mAttachInfo != null) {
13389                mAttachInfo.mViewVisibilityChanged = true;
13390            }
13391        }
13392
13393        if ((changed & VISIBILITY_MASK) != 0) {
13394            // If the view is invisible, cleanup its display list to free up resources
13395            if (newVisibility != VISIBLE && mAttachInfo != null) {
13396                cleanupDraw();
13397            }
13398
13399            if (mParent instanceof ViewGroup) {
13400                ((ViewGroup) mParent).onChildVisibilityChanged(this,
13401                        (changed & VISIBILITY_MASK), newVisibility);
13402                ((View) mParent).invalidate(true);
13403            } else if (mParent != null) {
13404                mParent.invalidateChild(this, null);
13405            }
13406
13407            if (mAttachInfo != null) {
13408                dispatchVisibilityChanged(this, newVisibility);
13409
13410                // Aggregated visibility changes are dispatched to attached views
13411                // in visible windows where the parent is currently shown/drawn
13412                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
13413                // discounting clipping or overlapping. This makes it a good place
13414                // to change animation states.
13415                if (mParent != null && getWindowVisibility() == VISIBLE &&
13416                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
13417                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
13418                }
13419                notifySubtreeAccessibilityStateChangedIfNeeded();
13420            }
13421        }
13422
13423        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
13424            destroyDrawingCache();
13425        }
13426
13427        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
13428            destroyDrawingCache();
13429            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13430            invalidateParentCaches();
13431        }
13432
13433        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
13434            destroyDrawingCache();
13435            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13436        }
13437
13438        if ((changed & DRAW_MASK) != 0) {
13439            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
13440                if (mBackground != null
13441                        || mDefaultFocusHighlight != null
13442                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
13443                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13444                } else {
13445                    mPrivateFlags |= PFLAG_SKIP_DRAW;
13446                }
13447            } else {
13448                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13449            }
13450            requestLayout();
13451            invalidate(true);
13452        }
13453
13454        if ((changed & KEEP_SCREEN_ON) != 0) {
13455            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13456                mParent.recomputeViewAttributes(this);
13457            }
13458        }
13459
13460        if (accessibilityEnabled) {
13461            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
13462                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
13463                    || (changed & CONTEXT_CLICKABLE) != 0) {
13464                if (oldIncludeForAccessibility != includeForAccessibility()) {
13465                    notifySubtreeAccessibilityStateChangedIfNeeded();
13466                } else {
13467                    notifyViewAccessibilityStateChangedIfNeeded(
13468                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13469                }
13470            } else if ((changed & ENABLED_MASK) != 0) {
13471                notifyViewAccessibilityStateChangedIfNeeded(
13472                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13473            }
13474        }
13475    }
13476
13477    /**
13478     * Change the view's z order in the tree, so it's on top of other sibling
13479     * views. This ordering change may affect layout, if the parent container
13480     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
13481     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
13482     * method should be followed by calls to {@link #requestLayout()} and
13483     * {@link View#invalidate()} on the view's parent to force the parent to redraw
13484     * with the new child ordering.
13485     *
13486     * @see ViewGroup#bringChildToFront(View)
13487     */
13488    public void bringToFront() {
13489        if (mParent != null) {
13490            mParent.bringChildToFront(this);
13491        }
13492    }
13493
13494    /**
13495     * This is called in response to an internal scroll in this view (i.e., the
13496     * view scrolled its own contents). This is typically as a result of
13497     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
13498     * called.
13499     *
13500     * @param l Current horizontal scroll origin.
13501     * @param t Current vertical scroll origin.
13502     * @param oldl Previous horizontal scroll origin.
13503     * @param oldt Previous vertical scroll origin.
13504     */
13505    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
13506        notifySubtreeAccessibilityStateChangedIfNeeded();
13507
13508        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13509            postSendViewScrolledAccessibilityEventCallback();
13510        }
13511
13512        mBackgroundSizeChanged = true;
13513        mDefaultFocusHighlightSizeChanged = true;
13514        if (mForegroundInfo != null) {
13515            mForegroundInfo.mBoundsChanged = true;
13516        }
13517
13518        final AttachInfo ai = mAttachInfo;
13519        if (ai != null) {
13520            ai.mViewScrollChanged = true;
13521        }
13522
13523        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
13524            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
13525        }
13526    }
13527
13528    /**
13529     * Interface definition for a callback to be invoked when the scroll
13530     * X or Y positions of a view change.
13531     * <p>
13532     * <b>Note:</b> Some views handle scrolling independently from View and may
13533     * have their own separate listeners for scroll-type events. For example,
13534     * {@link android.widget.ListView ListView} allows clients to register an
13535     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
13536     * to listen for changes in list scroll position.
13537     *
13538     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
13539     */
13540    public interface OnScrollChangeListener {
13541        /**
13542         * Called when the scroll position of a view changes.
13543         *
13544         * @param v The view whose scroll position has changed.
13545         * @param scrollX Current horizontal scroll origin.
13546         * @param scrollY Current vertical scroll origin.
13547         * @param oldScrollX Previous horizontal scroll origin.
13548         * @param oldScrollY Previous vertical scroll origin.
13549         */
13550        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13551    }
13552
13553    /**
13554     * Interface definition for a callback to be invoked when the layout bounds of a view
13555     * changes due to layout processing.
13556     */
13557    public interface OnLayoutChangeListener {
13558        /**
13559         * Called when the layout bounds of a view changes due to layout processing.
13560         *
13561         * @param v The view whose bounds have changed.
13562         * @param left The new value of the view's left property.
13563         * @param top The new value of the view's top property.
13564         * @param right The new value of the view's right property.
13565         * @param bottom The new value of the view's bottom property.
13566         * @param oldLeft The previous value of the view's left property.
13567         * @param oldTop The previous value of the view's top property.
13568         * @param oldRight The previous value of the view's right property.
13569         * @param oldBottom The previous value of the view's bottom property.
13570         */
13571        void onLayoutChange(View v, int left, int top, int right, int bottom,
13572            int oldLeft, int oldTop, int oldRight, int oldBottom);
13573    }
13574
13575    /**
13576     * This is called during layout when the size of this view has changed. If
13577     * you were just added to the view hierarchy, you're called with the old
13578     * values of 0.
13579     *
13580     * @param w Current width of this view.
13581     * @param h Current height of this view.
13582     * @param oldw Old width of this view.
13583     * @param oldh Old height of this view.
13584     */
13585    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13586    }
13587
13588    /**
13589     * Called by draw to draw the child views. This may be overridden
13590     * by derived classes to gain control just before its children are drawn
13591     * (but after its own view has been drawn).
13592     * @param canvas the canvas on which to draw the view
13593     */
13594    protected void dispatchDraw(Canvas canvas) {
13595
13596    }
13597
13598    /**
13599     * Gets the parent of this view. Note that the parent is a
13600     * ViewParent and not necessarily a View.
13601     *
13602     * @return Parent of this view.
13603     */
13604    public final ViewParent getParent() {
13605        return mParent;
13606    }
13607
13608    /**
13609     * Set the horizontal scrolled position of your view. This will cause a call to
13610     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13611     * invalidated.
13612     * @param value the x position to scroll to
13613     */
13614    public void setScrollX(int value) {
13615        scrollTo(value, mScrollY);
13616    }
13617
13618    /**
13619     * Set the vertical scrolled position of your view. This will cause a call to
13620     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13621     * invalidated.
13622     * @param value the y position to scroll to
13623     */
13624    public void setScrollY(int value) {
13625        scrollTo(mScrollX, value);
13626    }
13627
13628    /**
13629     * Return the scrolled left position of this view. This is the left edge of
13630     * the displayed part of your view. You do not need to draw any pixels
13631     * farther left, since those are outside of the frame of your view on
13632     * screen.
13633     *
13634     * @return The left edge of the displayed part of your view, in pixels.
13635     */
13636    public final int getScrollX() {
13637        return mScrollX;
13638    }
13639
13640    /**
13641     * Return the scrolled top position of this view. This is the top edge of
13642     * the displayed part of your view. You do not need to draw any pixels above
13643     * it, since those are outside of the frame of your view on screen.
13644     *
13645     * @return The top edge of the displayed part of your view, in pixels.
13646     */
13647    public final int getScrollY() {
13648        return mScrollY;
13649    }
13650
13651    /**
13652     * Return the width of the your view.
13653     *
13654     * @return The width of your view, in pixels.
13655     */
13656    @ViewDebug.ExportedProperty(category = "layout")
13657    public final int getWidth() {
13658        return mRight - mLeft;
13659    }
13660
13661    /**
13662     * Return the height of your view.
13663     *
13664     * @return The height of your view, in pixels.
13665     */
13666    @ViewDebug.ExportedProperty(category = "layout")
13667    public final int getHeight() {
13668        return mBottom - mTop;
13669    }
13670
13671    /**
13672     * Return the visible drawing bounds of your view. Fills in the output
13673     * rectangle with the values from getScrollX(), getScrollY(),
13674     * getWidth(), and getHeight(). These bounds do not account for any
13675     * transformation properties currently set on the view, such as
13676     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13677     *
13678     * @param outRect The (scrolled) drawing bounds of the view.
13679     */
13680    public void getDrawingRect(Rect outRect) {
13681        outRect.left = mScrollX;
13682        outRect.top = mScrollY;
13683        outRect.right = mScrollX + (mRight - mLeft);
13684        outRect.bottom = mScrollY + (mBottom - mTop);
13685    }
13686
13687    /**
13688     * Like {@link #getMeasuredWidthAndState()}, but only returns the
13689     * raw width component (that is the result is masked by
13690     * {@link #MEASURED_SIZE_MASK}).
13691     *
13692     * @return The raw measured width of this view.
13693     */
13694    public final int getMeasuredWidth() {
13695        return mMeasuredWidth & MEASURED_SIZE_MASK;
13696    }
13697
13698    /**
13699     * Return the full width measurement information for this view as computed
13700     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13701     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13702     * This should be used during measurement and layout calculations only. Use
13703     * {@link #getWidth()} to see how wide a view is after layout.
13704     *
13705     * @return The measured width of this view as a bit mask.
13706     */
13707    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13708            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13709                    name = "MEASURED_STATE_TOO_SMALL"),
13710    })
13711    public final int getMeasuredWidthAndState() {
13712        return mMeasuredWidth;
13713    }
13714
13715    /**
13716     * Like {@link #getMeasuredHeightAndState()}, but only returns the
13717     * raw height component (that is the result is masked by
13718     * {@link #MEASURED_SIZE_MASK}).
13719     *
13720     * @return The raw measured height of this view.
13721     */
13722    public final int getMeasuredHeight() {
13723        return mMeasuredHeight & MEASURED_SIZE_MASK;
13724    }
13725
13726    /**
13727     * Return the full height measurement information for this view as computed
13728     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13729     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13730     * This should be used during measurement and layout calculations only. Use
13731     * {@link #getHeight()} to see how wide a view is after layout.
13732     *
13733     * @return The measured height of this view as a bit mask.
13734     */
13735    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13736            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13737                    name = "MEASURED_STATE_TOO_SMALL"),
13738    })
13739    public final int getMeasuredHeightAndState() {
13740        return mMeasuredHeight;
13741    }
13742
13743    /**
13744     * Return only the state bits of {@link #getMeasuredWidthAndState()}
13745     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13746     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13747     * and the height component is at the shifted bits
13748     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13749     */
13750    public final int getMeasuredState() {
13751        return (mMeasuredWidth&MEASURED_STATE_MASK)
13752                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13753                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13754    }
13755
13756    /**
13757     * The transform matrix of this view, which is calculated based on the current
13758     * rotation, scale, and pivot properties.
13759     *
13760     * @see #getRotation()
13761     * @see #getScaleX()
13762     * @see #getScaleY()
13763     * @see #getPivotX()
13764     * @see #getPivotY()
13765     * @return The current transform matrix for the view
13766     */
13767    public Matrix getMatrix() {
13768        ensureTransformationInfo();
13769        final Matrix matrix = mTransformationInfo.mMatrix;
13770        mRenderNode.getMatrix(matrix);
13771        return matrix;
13772    }
13773
13774    /**
13775     * Returns true if the transform matrix is the identity matrix.
13776     * Recomputes the matrix if necessary.
13777     *
13778     * @return True if the transform matrix is the identity matrix, false otherwise.
13779     */
13780    final boolean hasIdentityMatrix() {
13781        return mRenderNode.hasIdentityMatrix();
13782    }
13783
13784    void ensureTransformationInfo() {
13785        if (mTransformationInfo == null) {
13786            mTransformationInfo = new TransformationInfo();
13787        }
13788    }
13789
13790    /**
13791     * Utility method to retrieve the inverse of the current mMatrix property.
13792     * We cache the matrix to avoid recalculating it when transform properties
13793     * have not changed.
13794     *
13795     * @return The inverse of the current matrix of this view.
13796     * @hide
13797     */
13798    public final Matrix getInverseMatrix() {
13799        ensureTransformationInfo();
13800        if (mTransformationInfo.mInverseMatrix == null) {
13801            mTransformationInfo.mInverseMatrix = new Matrix();
13802        }
13803        final Matrix matrix = mTransformationInfo.mInverseMatrix;
13804        mRenderNode.getInverseMatrix(matrix);
13805        return matrix;
13806    }
13807
13808    /**
13809     * Gets the distance along the Z axis from the camera to this view.
13810     *
13811     * @see #setCameraDistance(float)
13812     *
13813     * @return The distance along the Z axis.
13814     */
13815    public float getCameraDistance() {
13816        final float dpi = mResources.getDisplayMetrics().densityDpi;
13817        return -(mRenderNode.getCameraDistance() * dpi);
13818    }
13819
13820    /**
13821     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13822     * views are drawn) from the camera to this view. The camera's distance
13823     * affects 3D transformations, for instance rotations around the X and Y
13824     * axis. If the rotationX or rotationY properties are changed and this view is
13825     * large (more than half the size of the screen), it is recommended to always
13826     * use a camera distance that's greater than the height (X axis rotation) or
13827     * the width (Y axis rotation) of this view.</p>
13828     *
13829     * <p>The distance of the camera from the view plane can have an affect on the
13830     * perspective distortion of the view when it is rotated around the x or y axis.
13831     * For example, a large distance will result in a large viewing angle, and there
13832     * will not be much perspective distortion of the view as it rotates. A short
13833     * distance may cause much more perspective distortion upon rotation, and can
13834     * also result in some drawing artifacts if the rotated view ends up partially
13835     * behind the camera (which is why the recommendation is to use a distance at
13836     * least as far as the size of the view, if the view is to be rotated.)</p>
13837     *
13838     * <p>The distance is expressed in "depth pixels." The default distance depends
13839     * on the screen density. For instance, on a medium density display, the
13840     * default distance is 1280. On a high density display, the default distance
13841     * is 1920.</p>
13842     *
13843     * <p>If you want to specify a distance that leads to visually consistent
13844     * results across various densities, use the following formula:</p>
13845     * <pre>
13846     * float scale = context.getResources().getDisplayMetrics().density;
13847     * view.setCameraDistance(distance * scale);
13848     * </pre>
13849     *
13850     * <p>The density scale factor of a high density display is 1.5,
13851     * and 1920 = 1280 * 1.5.</p>
13852     *
13853     * @param distance The distance in "depth pixels", if negative the opposite
13854     *        value is used
13855     *
13856     * @see #setRotationX(float)
13857     * @see #setRotationY(float)
13858     */
13859    public void setCameraDistance(float distance) {
13860        final float dpi = mResources.getDisplayMetrics().densityDpi;
13861
13862        invalidateViewProperty(true, false);
13863        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13864        invalidateViewProperty(false, false);
13865
13866        invalidateParentIfNeededAndWasQuickRejected();
13867    }
13868
13869    /**
13870     * The degrees that the view is rotated around the pivot point.
13871     *
13872     * @see #setRotation(float)
13873     * @see #getPivotX()
13874     * @see #getPivotY()
13875     *
13876     * @return The degrees of rotation.
13877     */
13878    @ViewDebug.ExportedProperty(category = "drawing")
13879    public float getRotation() {
13880        return mRenderNode.getRotation();
13881    }
13882
13883    /**
13884     * Sets the degrees that the view is rotated around the pivot point. Increasing values
13885     * result in clockwise rotation.
13886     *
13887     * @param rotation The degrees of rotation.
13888     *
13889     * @see #getRotation()
13890     * @see #getPivotX()
13891     * @see #getPivotY()
13892     * @see #setRotationX(float)
13893     * @see #setRotationY(float)
13894     *
13895     * @attr ref android.R.styleable#View_rotation
13896     */
13897    public void setRotation(float rotation) {
13898        if (rotation != getRotation()) {
13899            // Double-invalidation is necessary to capture view's old and new areas
13900            invalidateViewProperty(true, false);
13901            mRenderNode.setRotation(rotation);
13902            invalidateViewProperty(false, true);
13903
13904            invalidateParentIfNeededAndWasQuickRejected();
13905            notifySubtreeAccessibilityStateChangedIfNeeded();
13906        }
13907    }
13908
13909    /**
13910     * The degrees that the view is rotated around the vertical axis through the pivot point.
13911     *
13912     * @see #getPivotX()
13913     * @see #getPivotY()
13914     * @see #setRotationY(float)
13915     *
13916     * @return The degrees of Y rotation.
13917     */
13918    @ViewDebug.ExportedProperty(category = "drawing")
13919    public float getRotationY() {
13920        return mRenderNode.getRotationY();
13921    }
13922
13923    /**
13924     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13925     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13926     * down the y axis.
13927     *
13928     * When rotating large views, it is recommended to adjust the camera distance
13929     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13930     *
13931     * @param rotationY The degrees of Y rotation.
13932     *
13933     * @see #getRotationY()
13934     * @see #getPivotX()
13935     * @see #getPivotY()
13936     * @see #setRotation(float)
13937     * @see #setRotationX(float)
13938     * @see #setCameraDistance(float)
13939     *
13940     * @attr ref android.R.styleable#View_rotationY
13941     */
13942    public void setRotationY(float rotationY) {
13943        if (rotationY != getRotationY()) {
13944            invalidateViewProperty(true, false);
13945            mRenderNode.setRotationY(rotationY);
13946            invalidateViewProperty(false, true);
13947
13948            invalidateParentIfNeededAndWasQuickRejected();
13949            notifySubtreeAccessibilityStateChangedIfNeeded();
13950        }
13951    }
13952
13953    /**
13954     * The degrees that the view is rotated around the horizontal axis through the pivot point.
13955     *
13956     * @see #getPivotX()
13957     * @see #getPivotY()
13958     * @see #setRotationX(float)
13959     *
13960     * @return The degrees of X rotation.
13961     */
13962    @ViewDebug.ExportedProperty(category = "drawing")
13963    public float getRotationX() {
13964        return mRenderNode.getRotationX();
13965    }
13966
13967    /**
13968     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13969     * Increasing values result in clockwise rotation from the viewpoint of looking down the
13970     * x axis.
13971     *
13972     * When rotating large views, it is recommended to adjust the camera distance
13973     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13974     *
13975     * @param rotationX The degrees of X rotation.
13976     *
13977     * @see #getRotationX()
13978     * @see #getPivotX()
13979     * @see #getPivotY()
13980     * @see #setRotation(float)
13981     * @see #setRotationY(float)
13982     * @see #setCameraDistance(float)
13983     *
13984     * @attr ref android.R.styleable#View_rotationX
13985     */
13986    public void setRotationX(float rotationX) {
13987        if (rotationX != getRotationX()) {
13988            invalidateViewProperty(true, false);
13989            mRenderNode.setRotationX(rotationX);
13990            invalidateViewProperty(false, true);
13991
13992            invalidateParentIfNeededAndWasQuickRejected();
13993            notifySubtreeAccessibilityStateChangedIfNeeded();
13994        }
13995    }
13996
13997    /**
13998     * The amount that the view is scaled in x around the pivot point, as a proportion of
13999     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
14000     *
14001     * <p>By default, this is 1.0f.
14002     *
14003     * @see #getPivotX()
14004     * @see #getPivotY()
14005     * @return The scaling factor.
14006     */
14007    @ViewDebug.ExportedProperty(category = "drawing")
14008    public float getScaleX() {
14009        return mRenderNode.getScaleX();
14010    }
14011
14012    /**
14013     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
14014     * the view's unscaled width. A value of 1 means that no scaling is applied.
14015     *
14016     * @param scaleX The scaling factor.
14017     * @see #getPivotX()
14018     * @see #getPivotY()
14019     *
14020     * @attr ref android.R.styleable#View_scaleX
14021     */
14022    public void setScaleX(float scaleX) {
14023        if (scaleX != getScaleX()) {
14024            invalidateViewProperty(true, false);
14025            mRenderNode.setScaleX(scaleX);
14026            invalidateViewProperty(false, true);
14027
14028            invalidateParentIfNeededAndWasQuickRejected();
14029            notifySubtreeAccessibilityStateChangedIfNeeded();
14030        }
14031    }
14032
14033    /**
14034     * The amount that the view is scaled in y around the pivot point, as a proportion of
14035     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
14036     *
14037     * <p>By default, this is 1.0f.
14038     *
14039     * @see #getPivotX()
14040     * @see #getPivotY()
14041     * @return The scaling factor.
14042     */
14043    @ViewDebug.ExportedProperty(category = "drawing")
14044    public float getScaleY() {
14045        return mRenderNode.getScaleY();
14046    }
14047
14048    /**
14049     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
14050     * the view's unscaled width. A value of 1 means that no scaling is applied.
14051     *
14052     * @param scaleY The scaling factor.
14053     * @see #getPivotX()
14054     * @see #getPivotY()
14055     *
14056     * @attr ref android.R.styleable#View_scaleY
14057     */
14058    public void setScaleY(float scaleY) {
14059        if (scaleY != getScaleY()) {
14060            invalidateViewProperty(true, false);
14061            mRenderNode.setScaleY(scaleY);
14062            invalidateViewProperty(false, true);
14063
14064            invalidateParentIfNeededAndWasQuickRejected();
14065            notifySubtreeAccessibilityStateChangedIfNeeded();
14066        }
14067    }
14068
14069    /**
14070     * The x location of the point around which the view is {@link #setRotation(float) rotated}
14071     * and {@link #setScaleX(float) scaled}.
14072     *
14073     * @see #getRotation()
14074     * @see #getScaleX()
14075     * @see #getScaleY()
14076     * @see #getPivotY()
14077     * @return The x location of the pivot point.
14078     *
14079     * @attr ref android.R.styleable#View_transformPivotX
14080     */
14081    @ViewDebug.ExportedProperty(category = "drawing")
14082    public float getPivotX() {
14083        return mRenderNode.getPivotX();
14084    }
14085
14086    /**
14087     * Sets the x location of the point around which the view is
14088     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
14089     * By default, the pivot point is centered on the object.
14090     * Setting this property disables this behavior and causes the view to use only the
14091     * explicitly set pivotX and pivotY values.
14092     *
14093     * @param pivotX The x location of the pivot point.
14094     * @see #getRotation()
14095     * @see #getScaleX()
14096     * @see #getScaleY()
14097     * @see #getPivotY()
14098     *
14099     * @attr ref android.R.styleable#View_transformPivotX
14100     */
14101    public void setPivotX(float pivotX) {
14102        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
14103            invalidateViewProperty(true, false);
14104            mRenderNode.setPivotX(pivotX);
14105            invalidateViewProperty(false, true);
14106
14107            invalidateParentIfNeededAndWasQuickRejected();
14108        }
14109    }
14110
14111    /**
14112     * The y location of the point around which the view is {@link #setRotation(float) rotated}
14113     * and {@link #setScaleY(float) scaled}.
14114     *
14115     * @see #getRotation()
14116     * @see #getScaleX()
14117     * @see #getScaleY()
14118     * @see #getPivotY()
14119     * @return The y location of the pivot point.
14120     *
14121     * @attr ref android.R.styleable#View_transformPivotY
14122     */
14123    @ViewDebug.ExportedProperty(category = "drawing")
14124    public float getPivotY() {
14125        return mRenderNode.getPivotY();
14126    }
14127
14128    /**
14129     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
14130     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
14131     * Setting this property disables this behavior and causes the view to use only the
14132     * explicitly set pivotX and pivotY values.
14133     *
14134     * @param pivotY The y location of the pivot point.
14135     * @see #getRotation()
14136     * @see #getScaleX()
14137     * @see #getScaleY()
14138     * @see #getPivotY()
14139     *
14140     * @attr ref android.R.styleable#View_transformPivotY
14141     */
14142    public void setPivotY(float pivotY) {
14143        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
14144            invalidateViewProperty(true, false);
14145            mRenderNode.setPivotY(pivotY);
14146            invalidateViewProperty(false, true);
14147
14148            invalidateParentIfNeededAndWasQuickRejected();
14149        }
14150    }
14151
14152    /**
14153     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
14154     * completely transparent and 1 means the view is completely opaque.
14155     *
14156     * <p>By default this is 1.0f.
14157     * @return The opacity of the view.
14158     */
14159    @ViewDebug.ExportedProperty(category = "drawing")
14160    public float getAlpha() {
14161        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
14162    }
14163
14164    /**
14165     * Sets the behavior for overlapping rendering for this view (see {@link
14166     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
14167     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
14168     * providing the value which is then used internally. That is, when {@link
14169     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
14170     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
14171     * instead.
14172     *
14173     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
14174     * instead of that returned by {@link #hasOverlappingRendering()}.
14175     *
14176     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
14177     */
14178    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
14179        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
14180        if (hasOverlappingRendering) {
14181            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14182        } else {
14183            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14184        }
14185    }
14186
14187    /**
14188     * Returns the value for overlapping rendering that is used internally. This is either
14189     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
14190     * the return value of {@link #hasOverlappingRendering()}, otherwise.
14191     *
14192     * @return The value for overlapping rendering being used internally.
14193     */
14194    public final boolean getHasOverlappingRendering() {
14195        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
14196                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
14197                hasOverlappingRendering();
14198    }
14199
14200    /**
14201     * Returns whether this View has content which overlaps.
14202     *
14203     * <p>This function, intended to be overridden by specific View types, is an optimization when
14204     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
14205     * an offscreen buffer and then composited into place, which can be expensive. If the view has
14206     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
14207     * directly. An example of overlapping rendering is a TextView with a background image, such as
14208     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
14209     * ImageView with only the foreground image. The default implementation returns true; subclasses
14210     * should override if they have cases which can be optimized.</p>
14211     *
14212     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
14213     * necessitates that a View return true if it uses the methods internally without passing the
14214     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
14215     *
14216     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
14217     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
14218     *
14219     * @return true if the content in this view might overlap, false otherwise.
14220     */
14221    @ViewDebug.ExportedProperty(category = "drawing")
14222    public boolean hasOverlappingRendering() {
14223        return true;
14224    }
14225
14226    /**
14227     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
14228     * completely transparent and 1 means the view is completely opaque.
14229     *
14230     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
14231     * can have significant performance implications, especially for large views. It is best to use
14232     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
14233     *
14234     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
14235     * strongly recommended for performance reasons to either override
14236     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
14237     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
14238     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
14239     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
14240     * of rendering cost, even for simple or small views. Starting with
14241     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
14242     * applied to the view at the rendering level.</p>
14243     *
14244     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
14245     * responsible for applying the opacity itself.</p>
14246     *
14247     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
14248     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
14249     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
14250     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
14251     *
14252     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
14253     * value will clip a View to its bounds, unless the View returns <code>false</code> from
14254     * {@link #hasOverlappingRendering}.</p>
14255     *
14256     * @param alpha The opacity of the view.
14257     *
14258     * @see #hasOverlappingRendering()
14259     * @see #setLayerType(int, android.graphics.Paint)
14260     *
14261     * @attr ref android.R.styleable#View_alpha
14262     */
14263    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
14264        ensureTransformationInfo();
14265        if (mTransformationInfo.mAlpha != alpha) {
14266            // Report visibility changes, which can affect children, to accessibility
14267            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
14268                notifySubtreeAccessibilityStateChangedIfNeeded();
14269            }
14270            mTransformationInfo.mAlpha = alpha;
14271            if (onSetAlpha((int) (alpha * 255))) {
14272                mPrivateFlags |= PFLAG_ALPHA_SET;
14273                // subclass is handling alpha - don't optimize rendering cache invalidation
14274                invalidateParentCaches();
14275                invalidate(true);
14276            } else {
14277                mPrivateFlags &= ~PFLAG_ALPHA_SET;
14278                invalidateViewProperty(true, false);
14279                mRenderNode.setAlpha(getFinalAlpha());
14280            }
14281        }
14282    }
14283
14284    /**
14285     * Faster version of setAlpha() which performs the same steps except there are
14286     * no calls to invalidate(). The caller of this function should perform proper invalidation
14287     * on the parent and this object. The return value indicates whether the subclass handles
14288     * alpha (the return value for onSetAlpha()).
14289     *
14290     * @param alpha The new value for the alpha property
14291     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
14292     *         the new value for the alpha property is different from the old value
14293     */
14294    boolean setAlphaNoInvalidation(float alpha) {
14295        ensureTransformationInfo();
14296        if (mTransformationInfo.mAlpha != alpha) {
14297            mTransformationInfo.mAlpha = alpha;
14298            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
14299            if (subclassHandlesAlpha) {
14300                mPrivateFlags |= PFLAG_ALPHA_SET;
14301                return true;
14302            } else {
14303                mPrivateFlags &= ~PFLAG_ALPHA_SET;
14304                mRenderNode.setAlpha(getFinalAlpha());
14305            }
14306        }
14307        return false;
14308    }
14309
14310    /**
14311     * This property is hidden and intended only for use by the Fade transition, which
14312     * animates it to produce a visual translucency that does not side-effect (or get
14313     * affected by) the real alpha property. This value is composited with the other
14314     * alpha value (and the AlphaAnimation value, when that is present) to produce
14315     * a final visual translucency result, which is what is passed into the DisplayList.
14316     *
14317     * @hide
14318     */
14319    public void setTransitionAlpha(float alpha) {
14320        ensureTransformationInfo();
14321        if (mTransformationInfo.mTransitionAlpha != alpha) {
14322            mTransformationInfo.mTransitionAlpha = alpha;
14323            mPrivateFlags &= ~PFLAG_ALPHA_SET;
14324            invalidateViewProperty(true, false);
14325            mRenderNode.setAlpha(getFinalAlpha());
14326        }
14327    }
14328
14329    /**
14330     * Calculates the visual alpha of this view, which is a combination of the actual
14331     * alpha value and the transitionAlpha value (if set).
14332     */
14333    private float getFinalAlpha() {
14334        if (mTransformationInfo != null) {
14335            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
14336        }
14337        return 1;
14338    }
14339
14340    /**
14341     * This property is hidden and intended only for use by the Fade transition, which
14342     * animates it to produce a visual translucency that does not side-effect (or get
14343     * affected by) the real alpha property. This value is composited with the other
14344     * alpha value (and the AlphaAnimation value, when that is present) to produce
14345     * a final visual translucency result, which is what is passed into the DisplayList.
14346     *
14347     * @hide
14348     */
14349    @ViewDebug.ExportedProperty(category = "drawing")
14350    public float getTransitionAlpha() {
14351        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
14352    }
14353
14354    /**
14355     * Top position of this view relative to its parent.
14356     *
14357     * @return The top of this view, in pixels.
14358     */
14359    @ViewDebug.CapturedViewProperty
14360    public final int getTop() {
14361        return mTop;
14362    }
14363
14364    /**
14365     * Sets the top position of this view relative to its parent. This method is meant to be called
14366     * by the layout system and should not generally be called otherwise, because the property
14367     * may be changed at any time by the layout.
14368     *
14369     * @param top The top of this view, in pixels.
14370     */
14371    public final void setTop(int top) {
14372        if (top != mTop) {
14373            final boolean matrixIsIdentity = hasIdentityMatrix();
14374            if (matrixIsIdentity) {
14375                if (mAttachInfo != null) {
14376                    int minTop;
14377                    int yLoc;
14378                    if (top < mTop) {
14379                        minTop = top;
14380                        yLoc = top - mTop;
14381                    } else {
14382                        minTop = mTop;
14383                        yLoc = 0;
14384                    }
14385                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
14386                }
14387            } else {
14388                // Double-invalidation is necessary to capture view's old and new areas
14389                invalidate(true);
14390            }
14391
14392            int width = mRight - mLeft;
14393            int oldHeight = mBottom - mTop;
14394
14395            mTop = top;
14396            mRenderNode.setTop(mTop);
14397
14398            sizeChange(width, mBottom - mTop, width, oldHeight);
14399
14400            if (!matrixIsIdentity) {
14401                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14402                invalidate(true);
14403            }
14404            mBackgroundSizeChanged = true;
14405            mDefaultFocusHighlightSizeChanged = true;
14406            if (mForegroundInfo != null) {
14407                mForegroundInfo.mBoundsChanged = true;
14408            }
14409            invalidateParentIfNeeded();
14410            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14411                // View was rejected last time it was drawn by its parent; this may have changed
14412                invalidateParentIfNeeded();
14413            }
14414        }
14415    }
14416
14417    /**
14418     * Bottom position of this view relative to its parent.
14419     *
14420     * @return The bottom of this view, in pixels.
14421     */
14422    @ViewDebug.CapturedViewProperty
14423    public final int getBottom() {
14424        return mBottom;
14425    }
14426
14427    /**
14428     * True if this view has changed since the last time being drawn.
14429     *
14430     * @return The dirty state of this view.
14431     */
14432    public boolean isDirty() {
14433        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
14434    }
14435
14436    /**
14437     * Sets the bottom position of this view relative to its parent. This method is meant to be
14438     * called by the layout system and should not generally be called otherwise, because the
14439     * property may be changed at any time by the layout.
14440     *
14441     * @param bottom The bottom of this view, in pixels.
14442     */
14443    public final void setBottom(int bottom) {
14444        if (bottom != mBottom) {
14445            final boolean matrixIsIdentity = hasIdentityMatrix();
14446            if (matrixIsIdentity) {
14447                if (mAttachInfo != null) {
14448                    int maxBottom;
14449                    if (bottom < mBottom) {
14450                        maxBottom = mBottom;
14451                    } else {
14452                        maxBottom = bottom;
14453                    }
14454                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
14455                }
14456            } else {
14457                // Double-invalidation is necessary to capture view's old and new areas
14458                invalidate(true);
14459            }
14460
14461            int width = mRight - mLeft;
14462            int oldHeight = mBottom - mTop;
14463
14464            mBottom = bottom;
14465            mRenderNode.setBottom(mBottom);
14466
14467            sizeChange(width, mBottom - mTop, width, oldHeight);
14468
14469            if (!matrixIsIdentity) {
14470                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14471                invalidate(true);
14472            }
14473            mBackgroundSizeChanged = true;
14474            mDefaultFocusHighlightSizeChanged = true;
14475            if (mForegroundInfo != null) {
14476                mForegroundInfo.mBoundsChanged = true;
14477            }
14478            invalidateParentIfNeeded();
14479            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14480                // View was rejected last time it was drawn by its parent; this may have changed
14481                invalidateParentIfNeeded();
14482            }
14483        }
14484    }
14485
14486    /**
14487     * Left position of this view relative to its parent.
14488     *
14489     * @return The left edge of this view, in pixels.
14490     */
14491    @ViewDebug.CapturedViewProperty
14492    public final int getLeft() {
14493        return mLeft;
14494    }
14495
14496    /**
14497     * Sets the left position of this view relative to its parent. This method is meant to be called
14498     * by the layout system and should not generally be called otherwise, because the property
14499     * may be changed at any time by the layout.
14500     *
14501     * @param left The left of this view, in pixels.
14502     */
14503    public final void setLeft(int left) {
14504        if (left != mLeft) {
14505            final boolean matrixIsIdentity = hasIdentityMatrix();
14506            if (matrixIsIdentity) {
14507                if (mAttachInfo != null) {
14508                    int minLeft;
14509                    int xLoc;
14510                    if (left < mLeft) {
14511                        minLeft = left;
14512                        xLoc = left - mLeft;
14513                    } else {
14514                        minLeft = mLeft;
14515                        xLoc = 0;
14516                    }
14517                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
14518                }
14519            } else {
14520                // Double-invalidation is necessary to capture view's old and new areas
14521                invalidate(true);
14522            }
14523
14524            int oldWidth = mRight - mLeft;
14525            int height = mBottom - mTop;
14526
14527            mLeft = left;
14528            mRenderNode.setLeft(left);
14529
14530            sizeChange(mRight - mLeft, height, oldWidth, height);
14531
14532            if (!matrixIsIdentity) {
14533                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14534                invalidate(true);
14535            }
14536            mBackgroundSizeChanged = true;
14537            mDefaultFocusHighlightSizeChanged = true;
14538            if (mForegroundInfo != null) {
14539                mForegroundInfo.mBoundsChanged = true;
14540            }
14541            invalidateParentIfNeeded();
14542            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14543                // View was rejected last time it was drawn by its parent; this may have changed
14544                invalidateParentIfNeeded();
14545            }
14546        }
14547    }
14548
14549    /**
14550     * Right position of this view relative to its parent.
14551     *
14552     * @return The right edge of this view, in pixels.
14553     */
14554    @ViewDebug.CapturedViewProperty
14555    public final int getRight() {
14556        return mRight;
14557    }
14558
14559    /**
14560     * Sets the right position of this view relative to its parent. This method is meant to be called
14561     * by the layout system and should not generally be called otherwise, because the property
14562     * may be changed at any time by the layout.
14563     *
14564     * @param right The right of this view, in pixels.
14565     */
14566    public final void setRight(int right) {
14567        if (right != mRight) {
14568            final boolean matrixIsIdentity = hasIdentityMatrix();
14569            if (matrixIsIdentity) {
14570                if (mAttachInfo != null) {
14571                    int maxRight;
14572                    if (right < mRight) {
14573                        maxRight = mRight;
14574                    } else {
14575                        maxRight = right;
14576                    }
14577                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14578                }
14579            } else {
14580                // Double-invalidation is necessary to capture view's old and new areas
14581                invalidate(true);
14582            }
14583
14584            int oldWidth = mRight - mLeft;
14585            int height = mBottom - mTop;
14586
14587            mRight = right;
14588            mRenderNode.setRight(mRight);
14589
14590            sizeChange(mRight - mLeft, height, oldWidth, height);
14591
14592            if (!matrixIsIdentity) {
14593                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14594                invalidate(true);
14595            }
14596            mBackgroundSizeChanged = true;
14597            mDefaultFocusHighlightSizeChanged = true;
14598            if (mForegroundInfo != null) {
14599                mForegroundInfo.mBoundsChanged = true;
14600            }
14601            invalidateParentIfNeeded();
14602            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14603                // View was rejected last time it was drawn by its parent; this may have changed
14604                invalidateParentIfNeeded();
14605            }
14606        }
14607    }
14608
14609    /**
14610     * The visual x position of this view, in pixels. This is equivalent to the
14611     * {@link #setTranslationX(float) translationX} property plus the current
14612     * {@link #getLeft() left} property.
14613     *
14614     * @return The visual x position of this view, in pixels.
14615     */
14616    @ViewDebug.ExportedProperty(category = "drawing")
14617    public float getX() {
14618        return mLeft + getTranslationX();
14619    }
14620
14621    /**
14622     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14623     * {@link #setTranslationX(float) translationX} property to be the difference between
14624     * the x value passed in and the current {@link #getLeft() left} property.
14625     *
14626     * @param x The visual x position of this view, in pixels.
14627     */
14628    public void setX(float x) {
14629        setTranslationX(x - mLeft);
14630    }
14631
14632    /**
14633     * The visual y position of this view, in pixels. This is equivalent to the
14634     * {@link #setTranslationY(float) translationY} property plus the current
14635     * {@link #getTop() top} property.
14636     *
14637     * @return The visual y position of this view, in pixels.
14638     */
14639    @ViewDebug.ExportedProperty(category = "drawing")
14640    public float getY() {
14641        return mTop + getTranslationY();
14642    }
14643
14644    /**
14645     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14646     * {@link #setTranslationY(float) translationY} property to be the difference between
14647     * the y value passed in and the current {@link #getTop() top} property.
14648     *
14649     * @param y The visual y position of this view, in pixels.
14650     */
14651    public void setY(float y) {
14652        setTranslationY(y - mTop);
14653    }
14654
14655    /**
14656     * The visual z position of this view, in pixels. This is equivalent to the
14657     * {@link #setTranslationZ(float) translationZ} property plus the current
14658     * {@link #getElevation() elevation} property.
14659     *
14660     * @return The visual z position of this view, in pixels.
14661     */
14662    @ViewDebug.ExportedProperty(category = "drawing")
14663    public float getZ() {
14664        return getElevation() + getTranslationZ();
14665    }
14666
14667    /**
14668     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14669     * {@link #setTranslationZ(float) translationZ} property to be the difference between
14670     * the x value passed in and the current {@link #getElevation() elevation} property.
14671     *
14672     * @param z The visual z position of this view, in pixels.
14673     */
14674    public void setZ(float z) {
14675        setTranslationZ(z - getElevation());
14676    }
14677
14678    /**
14679     * The base elevation of this view relative to its parent, in pixels.
14680     *
14681     * @return The base depth position of the view, in pixels.
14682     */
14683    @ViewDebug.ExportedProperty(category = "drawing")
14684    public float getElevation() {
14685        return mRenderNode.getElevation();
14686    }
14687
14688    /**
14689     * Sets the base elevation of this view, in pixels.
14690     *
14691     * @attr ref android.R.styleable#View_elevation
14692     */
14693    public void setElevation(float elevation) {
14694        if (elevation != getElevation()) {
14695            invalidateViewProperty(true, false);
14696            mRenderNode.setElevation(elevation);
14697            invalidateViewProperty(false, true);
14698
14699            invalidateParentIfNeededAndWasQuickRejected();
14700        }
14701    }
14702
14703    /**
14704     * The horizontal location of this view relative to its {@link #getLeft() left} position.
14705     * This position is post-layout, in addition to wherever the object's
14706     * layout placed it.
14707     *
14708     * @return The horizontal position of this view relative to its left position, in pixels.
14709     */
14710    @ViewDebug.ExportedProperty(category = "drawing")
14711    public float getTranslationX() {
14712        return mRenderNode.getTranslationX();
14713    }
14714
14715    /**
14716     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14717     * This effectively positions the object post-layout, in addition to wherever the object's
14718     * layout placed it.
14719     *
14720     * @param translationX The horizontal position of this view relative to its left position,
14721     * in pixels.
14722     *
14723     * @attr ref android.R.styleable#View_translationX
14724     */
14725    public void setTranslationX(float translationX) {
14726        if (translationX != getTranslationX()) {
14727            invalidateViewProperty(true, false);
14728            mRenderNode.setTranslationX(translationX);
14729            invalidateViewProperty(false, true);
14730
14731            invalidateParentIfNeededAndWasQuickRejected();
14732            notifySubtreeAccessibilityStateChangedIfNeeded();
14733        }
14734    }
14735
14736    /**
14737     * The vertical location of this view relative to its {@link #getTop() top} position.
14738     * This position is post-layout, in addition to wherever the object's
14739     * layout placed it.
14740     *
14741     * @return The vertical position of this view relative to its top position,
14742     * in pixels.
14743     */
14744    @ViewDebug.ExportedProperty(category = "drawing")
14745    public float getTranslationY() {
14746        return mRenderNode.getTranslationY();
14747    }
14748
14749    /**
14750     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14751     * This effectively positions the object post-layout, in addition to wherever the object's
14752     * layout placed it.
14753     *
14754     * @param translationY The vertical position of this view relative to its top position,
14755     * in pixels.
14756     *
14757     * @attr ref android.R.styleable#View_translationY
14758     */
14759    public void setTranslationY(float translationY) {
14760        if (translationY != getTranslationY()) {
14761            invalidateViewProperty(true, false);
14762            mRenderNode.setTranslationY(translationY);
14763            invalidateViewProperty(false, true);
14764
14765            invalidateParentIfNeededAndWasQuickRejected();
14766            notifySubtreeAccessibilityStateChangedIfNeeded();
14767        }
14768    }
14769
14770    /**
14771     * The depth location of this view relative to its {@link #getElevation() elevation}.
14772     *
14773     * @return The depth of this view relative to its elevation.
14774     */
14775    @ViewDebug.ExportedProperty(category = "drawing")
14776    public float getTranslationZ() {
14777        return mRenderNode.getTranslationZ();
14778    }
14779
14780    /**
14781     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14782     *
14783     * @attr ref android.R.styleable#View_translationZ
14784     */
14785    public void setTranslationZ(float translationZ) {
14786        if (translationZ != getTranslationZ()) {
14787            invalidateViewProperty(true, false);
14788            mRenderNode.setTranslationZ(translationZ);
14789            invalidateViewProperty(false, true);
14790
14791            invalidateParentIfNeededAndWasQuickRejected();
14792        }
14793    }
14794
14795    /** @hide */
14796    public void setAnimationMatrix(Matrix matrix) {
14797        invalidateViewProperty(true, false);
14798        mRenderNode.setAnimationMatrix(matrix);
14799        invalidateViewProperty(false, true);
14800
14801        invalidateParentIfNeededAndWasQuickRejected();
14802    }
14803
14804    /**
14805     * Returns the current StateListAnimator if exists.
14806     *
14807     * @return StateListAnimator or null if it does not exists
14808     * @see    #setStateListAnimator(android.animation.StateListAnimator)
14809     */
14810    public StateListAnimator getStateListAnimator() {
14811        return mStateListAnimator;
14812    }
14813
14814    /**
14815     * Attaches the provided StateListAnimator to this View.
14816     * <p>
14817     * Any previously attached StateListAnimator will be detached.
14818     *
14819     * @param stateListAnimator The StateListAnimator to update the view
14820     * @see android.animation.StateListAnimator
14821     */
14822    public void setStateListAnimator(StateListAnimator stateListAnimator) {
14823        if (mStateListAnimator == stateListAnimator) {
14824            return;
14825        }
14826        if (mStateListAnimator != null) {
14827            mStateListAnimator.setTarget(null);
14828        }
14829        mStateListAnimator = stateListAnimator;
14830        if (stateListAnimator != null) {
14831            stateListAnimator.setTarget(this);
14832            if (isAttachedToWindow()) {
14833                stateListAnimator.setState(getDrawableState());
14834            }
14835        }
14836    }
14837
14838    /**
14839     * Returns whether the Outline should be used to clip the contents of the View.
14840     * <p>
14841     * Note that this flag will only be respected if the View's Outline returns true from
14842     * {@link Outline#canClip()}.
14843     *
14844     * @see #setOutlineProvider(ViewOutlineProvider)
14845     * @see #setClipToOutline(boolean)
14846     */
14847    public final boolean getClipToOutline() {
14848        return mRenderNode.getClipToOutline();
14849    }
14850
14851    /**
14852     * Sets whether the View's Outline should be used to clip the contents of the View.
14853     * <p>
14854     * Only a single non-rectangular clip can be applied on a View at any time.
14855     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14856     * circular reveal} animation take priority over Outline clipping, and
14857     * child Outline clipping takes priority over Outline clipping done by a
14858     * parent.
14859     * <p>
14860     * Note that this flag will only be respected if the View's Outline returns true from
14861     * {@link Outline#canClip()}.
14862     *
14863     * @see #setOutlineProvider(ViewOutlineProvider)
14864     * @see #getClipToOutline()
14865     */
14866    public void setClipToOutline(boolean clipToOutline) {
14867        damageInParent();
14868        if (getClipToOutline() != clipToOutline) {
14869            mRenderNode.setClipToOutline(clipToOutline);
14870        }
14871    }
14872
14873    // correspond to the enum values of View_outlineProvider
14874    private static final int PROVIDER_BACKGROUND = 0;
14875    private static final int PROVIDER_NONE = 1;
14876    private static final int PROVIDER_BOUNDS = 2;
14877    private static final int PROVIDER_PADDED_BOUNDS = 3;
14878    private void setOutlineProviderFromAttribute(int providerInt) {
14879        switch (providerInt) {
14880            case PROVIDER_BACKGROUND:
14881                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14882                break;
14883            case PROVIDER_NONE:
14884                setOutlineProvider(null);
14885                break;
14886            case PROVIDER_BOUNDS:
14887                setOutlineProvider(ViewOutlineProvider.BOUNDS);
14888                break;
14889            case PROVIDER_PADDED_BOUNDS:
14890                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14891                break;
14892        }
14893    }
14894
14895    /**
14896     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14897     * the shape of the shadow it casts, and enables outline clipping.
14898     * <p>
14899     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14900     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14901     * outline provider with this method allows this behavior to be overridden.
14902     * <p>
14903     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14904     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14905     * <p>
14906     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14907     *
14908     * @see #setClipToOutline(boolean)
14909     * @see #getClipToOutline()
14910     * @see #getOutlineProvider()
14911     */
14912    public void setOutlineProvider(ViewOutlineProvider provider) {
14913        mOutlineProvider = provider;
14914        invalidateOutline();
14915    }
14916
14917    /**
14918     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14919     * that defines the shape of the shadow it casts, and enables outline clipping.
14920     *
14921     * @see #setOutlineProvider(ViewOutlineProvider)
14922     */
14923    public ViewOutlineProvider getOutlineProvider() {
14924        return mOutlineProvider;
14925    }
14926
14927    /**
14928     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14929     *
14930     * @see #setOutlineProvider(ViewOutlineProvider)
14931     */
14932    public void invalidateOutline() {
14933        rebuildOutline();
14934
14935        notifySubtreeAccessibilityStateChangedIfNeeded();
14936        invalidateViewProperty(false, false);
14937    }
14938
14939    /**
14940     * Internal version of {@link #invalidateOutline()} which invalidates the
14941     * outline without invalidating the view itself. This is intended to be called from
14942     * within methods in the View class itself which are the result of the view being
14943     * invalidated already. For example, when we are drawing the background of a View,
14944     * we invalidate the outline in case it changed in the meantime, but we do not
14945     * need to invalidate the view because we're already drawing the background as part
14946     * of drawing the view in response to an earlier invalidation of the view.
14947     */
14948    private void rebuildOutline() {
14949        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14950        if (mAttachInfo == null) return;
14951
14952        if (mOutlineProvider == null) {
14953            // no provider, remove outline
14954            mRenderNode.setOutline(null);
14955        } else {
14956            final Outline outline = mAttachInfo.mTmpOutline;
14957            outline.setEmpty();
14958            outline.setAlpha(1.0f);
14959
14960            mOutlineProvider.getOutline(this, outline);
14961            mRenderNode.setOutline(outline);
14962        }
14963    }
14964
14965    /**
14966     * HierarchyViewer only
14967     *
14968     * @hide
14969     */
14970    @ViewDebug.ExportedProperty(category = "drawing")
14971    public boolean hasShadow() {
14972        return mRenderNode.hasShadow();
14973    }
14974
14975
14976    /** @hide */
14977    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14978        mRenderNode.setRevealClip(shouldClip, x, y, radius);
14979        invalidateViewProperty(false, false);
14980    }
14981
14982    /**
14983     * Hit rectangle in parent's coordinates
14984     *
14985     * @param outRect The hit rectangle of the view.
14986     */
14987    public void getHitRect(Rect outRect) {
14988        if (hasIdentityMatrix() || mAttachInfo == null) {
14989            outRect.set(mLeft, mTop, mRight, mBottom);
14990        } else {
14991            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14992            tmpRect.set(0, 0, getWidth(), getHeight());
14993            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14994            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14995                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14996        }
14997    }
14998
14999    /**
15000     * Determines whether the given point, in local coordinates is inside the view.
15001     */
15002    /*package*/ final boolean pointInView(float localX, float localY) {
15003        return pointInView(localX, localY, 0);
15004    }
15005
15006    /**
15007     * Utility method to determine whether the given point, in local coordinates,
15008     * is inside the view, where the area of the view is expanded by the slop factor.
15009     * This method is called while processing touch-move events to determine if the event
15010     * is still within the view.
15011     *
15012     * @hide
15013     */
15014    public boolean pointInView(float localX, float localY, float slop) {
15015        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
15016                localY < ((mBottom - mTop) + slop);
15017    }
15018
15019    /**
15020     * When a view has focus and the user navigates away from it, the next view is searched for
15021     * starting from the rectangle filled in by this method.
15022     *
15023     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
15024     * of the view.  However, if your view maintains some idea of internal selection,
15025     * such as a cursor, or a selected row or column, you should override this method and
15026     * fill in a more specific rectangle.
15027     *
15028     * @param r The rectangle to fill in, in this view's coordinates.
15029     */
15030    public void getFocusedRect(Rect r) {
15031        getDrawingRect(r);
15032    }
15033
15034    /**
15035     * If some part of this view is not clipped by any of its parents, then
15036     * return that area in r in global (root) coordinates. To convert r to local
15037     * coordinates (without taking possible View rotations into account), offset
15038     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
15039     * If the view is completely clipped or translated out, return false.
15040     *
15041     * @param r If true is returned, r holds the global coordinates of the
15042     *        visible portion of this view.
15043     * @param globalOffset If true is returned, globalOffset holds the dx,dy
15044     *        between this view and its root. globalOffet may be null.
15045     * @return true if r is non-empty (i.e. part of the view is visible at the
15046     *         root level.
15047     */
15048    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
15049        int width = mRight - mLeft;
15050        int height = mBottom - mTop;
15051        if (width > 0 && height > 0) {
15052            r.set(0, 0, width, height);
15053            if (globalOffset != null) {
15054                globalOffset.set(-mScrollX, -mScrollY);
15055            }
15056            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
15057        }
15058        return false;
15059    }
15060
15061    public final boolean getGlobalVisibleRect(Rect r) {
15062        return getGlobalVisibleRect(r, null);
15063    }
15064
15065    public final boolean getLocalVisibleRect(Rect r) {
15066        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
15067        if (getGlobalVisibleRect(r, offset)) {
15068            r.offset(-offset.x, -offset.y); // make r local
15069            return true;
15070        }
15071        return false;
15072    }
15073
15074    /**
15075     * Offset this view's vertical location by the specified number of pixels.
15076     *
15077     * @param offset the number of pixels to offset the view by
15078     */
15079    public void offsetTopAndBottom(int offset) {
15080        if (offset != 0) {
15081            final boolean matrixIsIdentity = hasIdentityMatrix();
15082            if (matrixIsIdentity) {
15083                if (isHardwareAccelerated()) {
15084                    invalidateViewProperty(false, false);
15085                } else {
15086                    final ViewParent p = mParent;
15087                    if (p != null && mAttachInfo != null) {
15088                        final Rect r = mAttachInfo.mTmpInvalRect;
15089                        int minTop;
15090                        int maxBottom;
15091                        int yLoc;
15092                        if (offset < 0) {
15093                            minTop = mTop + offset;
15094                            maxBottom = mBottom;
15095                            yLoc = offset;
15096                        } else {
15097                            minTop = mTop;
15098                            maxBottom = mBottom + offset;
15099                            yLoc = 0;
15100                        }
15101                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
15102                        p.invalidateChild(this, r);
15103                    }
15104                }
15105            } else {
15106                invalidateViewProperty(false, false);
15107            }
15108
15109            mTop += offset;
15110            mBottom += offset;
15111            mRenderNode.offsetTopAndBottom(offset);
15112            if (isHardwareAccelerated()) {
15113                invalidateViewProperty(false, false);
15114                invalidateParentIfNeededAndWasQuickRejected();
15115            } else {
15116                if (!matrixIsIdentity) {
15117                    invalidateViewProperty(false, true);
15118                }
15119                invalidateParentIfNeeded();
15120            }
15121            notifySubtreeAccessibilityStateChangedIfNeeded();
15122        }
15123    }
15124
15125    /**
15126     * Offset this view's horizontal location by the specified amount of pixels.
15127     *
15128     * @param offset the number of pixels to offset the view by
15129     */
15130    public void offsetLeftAndRight(int offset) {
15131        if (offset != 0) {
15132            final boolean matrixIsIdentity = hasIdentityMatrix();
15133            if (matrixIsIdentity) {
15134                if (isHardwareAccelerated()) {
15135                    invalidateViewProperty(false, false);
15136                } else {
15137                    final ViewParent p = mParent;
15138                    if (p != null && mAttachInfo != null) {
15139                        final Rect r = mAttachInfo.mTmpInvalRect;
15140                        int minLeft;
15141                        int maxRight;
15142                        if (offset < 0) {
15143                            minLeft = mLeft + offset;
15144                            maxRight = mRight;
15145                        } else {
15146                            minLeft = mLeft;
15147                            maxRight = mRight + offset;
15148                        }
15149                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
15150                        p.invalidateChild(this, r);
15151                    }
15152                }
15153            } else {
15154                invalidateViewProperty(false, false);
15155            }
15156
15157            mLeft += offset;
15158            mRight += offset;
15159            mRenderNode.offsetLeftAndRight(offset);
15160            if (isHardwareAccelerated()) {
15161                invalidateViewProperty(false, false);
15162                invalidateParentIfNeededAndWasQuickRejected();
15163            } else {
15164                if (!matrixIsIdentity) {
15165                    invalidateViewProperty(false, true);
15166                }
15167                invalidateParentIfNeeded();
15168            }
15169            notifySubtreeAccessibilityStateChangedIfNeeded();
15170        }
15171    }
15172
15173    /**
15174     * Get the LayoutParams associated with this view. All views should have
15175     * layout parameters. These supply parameters to the <i>parent</i> of this
15176     * view specifying how it should be arranged. There are many subclasses of
15177     * ViewGroup.LayoutParams, and these correspond to the different subclasses
15178     * of ViewGroup that are responsible for arranging their children.
15179     *
15180     * This method may return null if this View is not attached to a parent
15181     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
15182     * was not invoked successfully. When a View is attached to a parent
15183     * ViewGroup, this method must not return null.
15184     *
15185     * @return The LayoutParams associated with this view, or null if no
15186     *         parameters have been set yet
15187     */
15188    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
15189    public ViewGroup.LayoutParams getLayoutParams() {
15190        return mLayoutParams;
15191    }
15192
15193    /**
15194     * Set the layout parameters associated with this view. These supply
15195     * parameters to the <i>parent</i> of this view specifying how it should be
15196     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
15197     * correspond to the different subclasses of ViewGroup that are responsible
15198     * for arranging their children.
15199     *
15200     * @param params The layout parameters for this view, cannot be null
15201     */
15202    public void setLayoutParams(ViewGroup.LayoutParams params) {
15203        if (params == null) {
15204            throw new NullPointerException("Layout parameters cannot be null");
15205        }
15206        mLayoutParams = params;
15207        resolveLayoutParams();
15208        if (mParent instanceof ViewGroup) {
15209            ((ViewGroup) mParent).onSetLayoutParams(this, params);
15210        }
15211        requestLayout();
15212    }
15213
15214    /**
15215     * Resolve the layout parameters depending on the resolved layout direction
15216     *
15217     * @hide
15218     */
15219    public void resolveLayoutParams() {
15220        if (mLayoutParams != null) {
15221            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
15222        }
15223    }
15224
15225    /**
15226     * Set the scrolled position of your view. This will cause a call to
15227     * {@link #onScrollChanged(int, int, int, int)} and the view will be
15228     * invalidated.
15229     * @param x the x position to scroll to
15230     * @param y the y position to scroll to
15231     */
15232    public void scrollTo(int x, int y) {
15233        if (mScrollX != x || mScrollY != y) {
15234            int oldX = mScrollX;
15235            int oldY = mScrollY;
15236            mScrollX = x;
15237            mScrollY = y;
15238            invalidateParentCaches();
15239            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
15240            if (!awakenScrollBars()) {
15241                postInvalidateOnAnimation();
15242            }
15243        }
15244    }
15245
15246    /**
15247     * Move the scrolled position of your view. This will cause a call to
15248     * {@link #onScrollChanged(int, int, int, int)} and the view will be
15249     * invalidated.
15250     * @param x the amount of pixels to scroll by horizontally
15251     * @param y the amount of pixels to scroll by vertically
15252     */
15253    public void scrollBy(int x, int y) {
15254        scrollTo(mScrollX + x, mScrollY + y);
15255    }
15256
15257    /**
15258     * <p>Trigger the scrollbars to draw. When invoked this method starts an
15259     * animation to fade the scrollbars out after a default delay. If a subclass
15260     * provides animated scrolling, the start delay should equal the duration
15261     * of the scrolling animation.</p>
15262     *
15263     * <p>The animation starts only if at least one of the scrollbars is
15264     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
15265     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15266     * this method returns true, and false otherwise. If the animation is
15267     * started, this method calls {@link #invalidate()}; in that case the
15268     * caller should not call {@link #invalidate()}.</p>
15269     *
15270     * <p>This method should be invoked every time a subclass directly updates
15271     * the scroll parameters.</p>
15272     *
15273     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
15274     * and {@link #scrollTo(int, int)}.</p>
15275     *
15276     * @return true if the animation is played, false otherwise
15277     *
15278     * @see #awakenScrollBars(int)
15279     * @see #scrollBy(int, int)
15280     * @see #scrollTo(int, int)
15281     * @see #isHorizontalScrollBarEnabled()
15282     * @see #isVerticalScrollBarEnabled()
15283     * @see #setHorizontalScrollBarEnabled(boolean)
15284     * @see #setVerticalScrollBarEnabled(boolean)
15285     */
15286    protected boolean awakenScrollBars() {
15287        return mScrollCache != null &&
15288                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
15289    }
15290
15291    /**
15292     * Trigger the scrollbars to draw.
15293     * This method differs from awakenScrollBars() only in its default duration.
15294     * initialAwakenScrollBars() will show the scroll bars for longer than
15295     * usual to give the user more of a chance to notice them.
15296     *
15297     * @return true if the animation is played, false otherwise.
15298     */
15299    private boolean initialAwakenScrollBars() {
15300        return mScrollCache != null &&
15301                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
15302    }
15303
15304    /**
15305     * <p>
15306     * Trigger the scrollbars to draw. When invoked this method starts an
15307     * animation to fade the scrollbars out after a fixed delay. If a subclass
15308     * provides animated scrolling, the start delay should equal the duration of
15309     * the scrolling animation.
15310     * </p>
15311     *
15312     * <p>
15313     * The animation starts only if at least one of the scrollbars is enabled,
15314     * as specified by {@link #isHorizontalScrollBarEnabled()} and
15315     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15316     * this method returns true, and false otherwise. If the animation is
15317     * started, this method calls {@link #invalidate()}; in that case the caller
15318     * should not call {@link #invalidate()}.
15319     * </p>
15320     *
15321     * <p>
15322     * This method should be invoked every time a subclass directly updates the
15323     * scroll parameters.
15324     * </p>
15325     *
15326     * @param startDelay the delay, in milliseconds, after which the animation
15327     *        should start; when the delay is 0, the animation starts
15328     *        immediately
15329     * @return true if the animation is played, false otherwise
15330     *
15331     * @see #scrollBy(int, int)
15332     * @see #scrollTo(int, int)
15333     * @see #isHorizontalScrollBarEnabled()
15334     * @see #isVerticalScrollBarEnabled()
15335     * @see #setHorizontalScrollBarEnabled(boolean)
15336     * @see #setVerticalScrollBarEnabled(boolean)
15337     */
15338    protected boolean awakenScrollBars(int startDelay) {
15339        return awakenScrollBars(startDelay, true);
15340    }
15341
15342    /**
15343     * <p>
15344     * Trigger the scrollbars to draw. When invoked this method starts an
15345     * animation to fade the scrollbars out after a fixed delay. If a subclass
15346     * provides animated scrolling, the start delay should equal the duration of
15347     * the scrolling animation.
15348     * </p>
15349     *
15350     * <p>
15351     * The animation starts only if at least one of the scrollbars is enabled,
15352     * as specified by {@link #isHorizontalScrollBarEnabled()} and
15353     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15354     * this method returns true, and false otherwise. If the animation is
15355     * started, this method calls {@link #invalidate()} if the invalidate parameter
15356     * is set to true; in that case the caller
15357     * should not call {@link #invalidate()}.
15358     * </p>
15359     *
15360     * <p>
15361     * This method should be invoked every time a subclass directly updates the
15362     * scroll parameters.
15363     * </p>
15364     *
15365     * @param startDelay the delay, in milliseconds, after which the animation
15366     *        should start; when the delay is 0, the animation starts
15367     *        immediately
15368     *
15369     * @param invalidate Whether this method should call invalidate
15370     *
15371     * @return true if the animation is played, false otherwise
15372     *
15373     * @see #scrollBy(int, int)
15374     * @see #scrollTo(int, int)
15375     * @see #isHorizontalScrollBarEnabled()
15376     * @see #isVerticalScrollBarEnabled()
15377     * @see #setHorizontalScrollBarEnabled(boolean)
15378     * @see #setVerticalScrollBarEnabled(boolean)
15379     */
15380    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
15381        final ScrollabilityCache scrollCache = mScrollCache;
15382
15383        if (scrollCache == null || !scrollCache.fadeScrollBars) {
15384            return false;
15385        }
15386
15387        if (scrollCache.scrollBar == null) {
15388            scrollCache.scrollBar = new ScrollBarDrawable();
15389            scrollCache.scrollBar.setState(getDrawableState());
15390            scrollCache.scrollBar.setCallback(this);
15391        }
15392
15393        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
15394
15395            if (invalidate) {
15396                // Invalidate to show the scrollbars
15397                postInvalidateOnAnimation();
15398            }
15399
15400            if (scrollCache.state == ScrollabilityCache.OFF) {
15401                // FIXME: this is copied from WindowManagerService.
15402                // We should get this value from the system when it
15403                // is possible to do so.
15404                final int KEY_REPEAT_FIRST_DELAY = 750;
15405                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
15406            }
15407
15408            // Tell mScrollCache when we should start fading. This may
15409            // extend the fade start time if one was already scheduled
15410            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
15411            scrollCache.fadeStartTime = fadeStartTime;
15412            scrollCache.state = ScrollabilityCache.ON;
15413
15414            // Schedule our fader to run, unscheduling any old ones first
15415            if (mAttachInfo != null) {
15416                mAttachInfo.mHandler.removeCallbacks(scrollCache);
15417                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
15418            }
15419
15420            return true;
15421        }
15422
15423        return false;
15424    }
15425
15426    /**
15427     * Do not invalidate views which are not visible and which are not running an animation. They
15428     * will not get drawn and they should not set dirty flags as if they will be drawn
15429     */
15430    private boolean skipInvalidate() {
15431        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
15432                (!(mParent instanceof ViewGroup) ||
15433                        !((ViewGroup) mParent).isViewTransitioning(this));
15434    }
15435
15436    /**
15437     * Mark the area defined by dirty as needing to be drawn. If the view is
15438     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15439     * point in the future.
15440     * <p>
15441     * This must be called from a UI thread. To call from a non-UI thread, call
15442     * {@link #postInvalidate()}.
15443     * <p>
15444     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
15445     * {@code dirty}.
15446     *
15447     * @param dirty the rectangle representing the bounds of the dirty region
15448     */
15449    public void invalidate(Rect dirty) {
15450        final int scrollX = mScrollX;
15451        final int scrollY = mScrollY;
15452        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
15453                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
15454    }
15455
15456    /**
15457     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
15458     * coordinates of the dirty rect are relative to the view. If the view is
15459     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15460     * point in the future.
15461     * <p>
15462     * This must be called from a UI thread. To call from a non-UI thread, call
15463     * {@link #postInvalidate()}.
15464     *
15465     * @param l the left position of the dirty region
15466     * @param t the top position of the dirty region
15467     * @param r the right position of the dirty region
15468     * @param b the bottom position of the dirty region
15469     */
15470    public void invalidate(int l, int t, int r, int b) {
15471        final int scrollX = mScrollX;
15472        final int scrollY = mScrollY;
15473        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
15474    }
15475
15476    /**
15477     * Invalidate the whole view. If the view is visible,
15478     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
15479     * the future.
15480     * <p>
15481     * This must be called from a UI thread. To call from a non-UI thread, call
15482     * {@link #postInvalidate()}.
15483     */
15484    public void invalidate() {
15485        invalidate(true);
15486    }
15487
15488    /**
15489     * This is where the invalidate() work actually happens. A full invalidate()
15490     * causes the drawing cache to be invalidated, but this function can be
15491     * called with invalidateCache set to false to skip that invalidation step
15492     * for cases that do not need it (for example, a component that remains at
15493     * the same dimensions with the same content).
15494     *
15495     * @param invalidateCache Whether the drawing cache for this view should be
15496     *            invalidated as well. This is usually true for a full
15497     *            invalidate, but may be set to false if the View's contents or
15498     *            dimensions have not changed.
15499     * @hide
15500     */
15501    public void invalidate(boolean invalidateCache) {
15502        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
15503    }
15504
15505    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
15506            boolean fullInvalidate) {
15507        if (mGhostView != null) {
15508            mGhostView.invalidate(true);
15509            return;
15510        }
15511
15512        if (skipInvalidate()) {
15513            return;
15514        }
15515
15516        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
15517                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
15518                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
15519                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
15520            if (fullInvalidate) {
15521                mLastIsOpaque = isOpaque();
15522                mPrivateFlags &= ~PFLAG_DRAWN;
15523            }
15524
15525            mPrivateFlags |= PFLAG_DIRTY;
15526
15527            if (invalidateCache) {
15528                mPrivateFlags |= PFLAG_INVALIDATED;
15529                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15530            }
15531
15532            // Propagate the damage rectangle to the parent view.
15533            final AttachInfo ai = mAttachInfo;
15534            final ViewParent p = mParent;
15535            if (p != null && ai != null && l < r && t < b) {
15536                final Rect damage = ai.mTmpInvalRect;
15537                damage.set(l, t, r, b);
15538                p.invalidateChild(this, damage);
15539            }
15540
15541            // Damage the entire projection receiver, if necessary.
15542            if (mBackground != null && mBackground.isProjected()) {
15543                final View receiver = getProjectionReceiver();
15544                if (receiver != null) {
15545                    receiver.damageInParent();
15546                }
15547            }
15548        }
15549    }
15550
15551    /**
15552     * @return this view's projection receiver, or {@code null} if none exists
15553     */
15554    private View getProjectionReceiver() {
15555        ViewParent p = getParent();
15556        while (p != null && p instanceof View) {
15557            final View v = (View) p;
15558            if (v.isProjectionReceiver()) {
15559                return v;
15560            }
15561            p = p.getParent();
15562        }
15563
15564        return null;
15565    }
15566
15567    /**
15568     * @return whether the view is a projection receiver
15569     */
15570    private boolean isProjectionReceiver() {
15571        return mBackground != null;
15572    }
15573
15574    /**
15575     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15576     * set any flags or handle all of the cases handled by the default invalidation methods.
15577     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15578     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15579     * walk up the hierarchy, transforming the dirty rect as necessary.
15580     *
15581     * The method also handles normal invalidation logic if display list properties are not
15582     * being used in this view. The invalidateParent and forceRedraw flags are used by that
15583     * backup approach, to handle these cases used in the various property-setting methods.
15584     *
15585     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15586     * are not being used in this view
15587     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15588     * list properties are not being used in this view
15589     */
15590    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15591        if (!isHardwareAccelerated()
15592                || !mRenderNode.isValid()
15593                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15594            if (invalidateParent) {
15595                invalidateParentCaches();
15596            }
15597            if (forceRedraw) {
15598                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15599            }
15600            invalidate(false);
15601        } else {
15602            damageInParent();
15603        }
15604    }
15605
15606    /**
15607     * Tells the parent view to damage this view's bounds.
15608     *
15609     * @hide
15610     */
15611    protected void damageInParent() {
15612        if (mParent != null && mAttachInfo != null) {
15613            mParent.onDescendantInvalidated(this, this);
15614        }
15615    }
15616
15617    /**
15618     * Utility method to transform a given Rect by the current matrix of this view.
15619     */
15620    void transformRect(final Rect rect) {
15621        if (!getMatrix().isIdentity()) {
15622            RectF boundingRect = mAttachInfo.mTmpTransformRect;
15623            boundingRect.set(rect);
15624            getMatrix().mapRect(boundingRect);
15625            rect.set((int) Math.floor(boundingRect.left),
15626                    (int) Math.floor(boundingRect.top),
15627                    (int) Math.ceil(boundingRect.right),
15628                    (int) Math.ceil(boundingRect.bottom));
15629        }
15630    }
15631
15632    /**
15633     * Used to indicate that the parent of this view should clear its caches. This functionality
15634     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15635     * which is necessary when various parent-managed properties of the view change, such as
15636     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15637     * clears the parent caches and does not causes an invalidate event.
15638     *
15639     * @hide
15640     */
15641    protected void invalidateParentCaches() {
15642        if (mParent instanceof View) {
15643            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15644        }
15645    }
15646
15647    /**
15648     * Used to indicate that the parent of this view should be invalidated. This functionality
15649     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15650     * which is necessary when various parent-managed properties of the view change, such as
15651     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15652     * an invalidation event to the parent.
15653     *
15654     * @hide
15655     */
15656    protected void invalidateParentIfNeeded() {
15657        if (isHardwareAccelerated() && mParent instanceof View) {
15658            ((View) mParent).invalidate(true);
15659        }
15660    }
15661
15662    /**
15663     * @hide
15664     */
15665    protected void invalidateParentIfNeededAndWasQuickRejected() {
15666        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15667            // View was rejected last time it was drawn by its parent; this may have changed
15668            invalidateParentIfNeeded();
15669        }
15670    }
15671
15672    /**
15673     * Indicates whether this View is opaque. An opaque View guarantees that it will
15674     * draw all the pixels overlapping its bounds using a fully opaque color.
15675     *
15676     * Subclasses of View should override this method whenever possible to indicate
15677     * whether an instance is opaque. Opaque Views are treated in a special way by
15678     * the View hierarchy, possibly allowing it to perform optimizations during
15679     * invalidate/draw passes.
15680     *
15681     * @return True if this View is guaranteed to be fully opaque, false otherwise.
15682     */
15683    @ViewDebug.ExportedProperty(category = "drawing")
15684    public boolean isOpaque() {
15685        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15686                getFinalAlpha() >= 1.0f;
15687    }
15688
15689    /**
15690     * @hide
15691     */
15692    protected void computeOpaqueFlags() {
15693        // Opaque if:
15694        //   - Has a background
15695        //   - Background is opaque
15696        //   - Doesn't have scrollbars or scrollbars overlay
15697
15698        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15699            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15700        } else {
15701            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15702        }
15703
15704        final int flags = mViewFlags;
15705        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15706                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15707                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15708            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15709        } else {
15710            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15711        }
15712    }
15713
15714    /**
15715     * @hide
15716     */
15717    protected boolean hasOpaqueScrollbars() {
15718        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15719    }
15720
15721    /**
15722     * @return A handler associated with the thread running the View. This
15723     * handler can be used to pump events in the UI events queue.
15724     */
15725    public Handler getHandler() {
15726        final AttachInfo attachInfo = mAttachInfo;
15727        if (attachInfo != null) {
15728            return attachInfo.mHandler;
15729        }
15730        return null;
15731    }
15732
15733    /**
15734     * Returns the queue of runnable for this view.
15735     *
15736     * @return the queue of runnables for this view
15737     */
15738    private HandlerActionQueue getRunQueue() {
15739        if (mRunQueue == null) {
15740            mRunQueue = new HandlerActionQueue();
15741        }
15742        return mRunQueue;
15743    }
15744
15745    /**
15746     * Gets the view root associated with the View.
15747     * @return The view root, or null if none.
15748     * @hide
15749     */
15750    public ViewRootImpl getViewRootImpl() {
15751        if (mAttachInfo != null) {
15752            return mAttachInfo.mViewRootImpl;
15753        }
15754        return null;
15755    }
15756
15757    /**
15758     * @hide
15759     */
15760    public ThreadedRenderer getThreadedRenderer() {
15761        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15762    }
15763
15764    /**
15765     * <p>Causes the Runnable to be added to the message queue.
15766     * The runnable will be run on the user interface thread.</p>
15767     *
15768     * @param action The Runnable that will be executed.
15769     *
15770     * @return Returns true if the Runnable was successfully placed in to the
15771     *         message queue.  Returns false on failure, usually because the
15772     *         looper processing the message queue is exiting.
15773     *
15774     * @see #postDelayed
15775     * @see #removeCallbacks
15776     */
15777    public boolean post(Runnable action) {
15778        final AttachInfo attachInfo = mAttachInfo;
15779        if (attachInfo != null) {
15780            return attachInfo.mHandler.post(action);
15781        }
15782
15783        // Postpone the runnable until we know on which thread it needs to run.
15784        // Assume that the runnable will be successfully placed after attach.
15785        getRunQueue().post(action);
15786        return true;
15787    }
15788
15789    /**
15790     * <p>Causes the Runnable to be added to the message queue, to be run
15791     * after the specified amount of time elapses.
15792     * The runnable will be run on the user interface thread.</p>
15793     *
15794     * @param action The Runnable that will be executed.
15795     * @param delayMillis The delay (in milliseconds) until the Runnable
15796     *        will be executed.
15797     *
15798     * @return true if the Runnable was successfully placed in to the
15799     *         message queue.  Returns false on failure, usually because the
15800     *         looper processing the message queue is exiting.  Note that a
15801     *         result of true does not mean the Runnable will be processed --
15802     *         if the looper is quit before the delivery time of the message
15803     *         occurs then the message will be dropped.
15804     *
15805     * @see #post
15806     * @see #removeCallbacks
15807     */
15808    public boolean postDelayed(Runnable action, long delayMillis) {
15809        final AttachInfo attachInfo = mAttachInfo;
15810        if (attachInfo != null) {
15811            return attachInfo.mHandler.postDelayed(action, delayMillis);
15812        }
15813
15814        // Postpone the runnable until we know on which thread it needs to run.
15815        // Assume that the runnable will be successfully placed after attach.
15816        getRunQueue().postDelayed(action, delayMillis);
15817        return true;
15818    }
15819
15820    /**
15821     * <p>Causes the Runnable to execute on the next animation time step.
15822     * The runnable will be run on the user interface thread.</p>
15823     *
15824     * @param action The Runnable that will be executed.
15825     *
15826     * @see #postOnAnimationDelayed
15827     * @see #removeCallbacks
15828     */
15829    public void postOnAnimation(Runnable action) {
15830        final AttachInfo attachInfo = mAttachInfo;
15831        if (attachInfo != null) {
15832            attachInfo.mViewRootImpl.mChoreographer.postCallback(
15833                    Choreographer.CALLBACK_ANIMATION, action, null);
15834        } else {
15835            // Postpone the runnable until we know
15836            // on which thread it needs to run.
15837            getRunQueue().post(action);
15838        }
15839    }
15840
15841    /**
15842     * <p>Causes the Runnable to execute on the next animation time step,
15843     * after the specified amount of time elapses.
15844     * The runnable will be run on the user interface thread.</p>
15845     *
15846     * @param action The Runnable that will be executed.
15847     * @param delayMillis The delay (in milliseconds) until the Runnable
15848     *        will be executed.
15849     *
15850     * @see #postOnAnimation
15851     * @see #removeCallbacks
15852     */
15853    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15854        final AttachInfo attachInfo = mAttachInfo;
15855        if (attachInfo != null) {
15856            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15857                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15858        } else {
15859            // Postpone the runnable until we know
15860            // on which thread it needs to run.
15861            getRunQueue().postDelayed(action, delayMillis);
15862        }
15863    }
15864
15865    /**
15866     * <p>Removes the specified Runnable from the message queue.</p>
15867     *
15868     * @param action The Runnable to remove from the message handling queue
15869     *
15870     * @return true if this view could ask the Handler to remove the Runnable,
15871     *         false otherwise. When the returned value is true, the Runnable
15872     *         may or may not have been actually removed from the message queue
15873     *         (for instance, if the Runnable was not in the queue already.)
15874     *
15875     * @see #post
15876     * @see #postDelayed
15877     * @see #postOnAnimation
15878     * @see #postOnAnimationDelayed
15879     */
15880    public boolean removeCallbacks(Runnable action) {
15881        if (action != null) {
15882            final AttachInfo attachInfo = mAttachInfo;
15883            if (attachInfo != null) {
15884                attachInfo.mHandler.removeCallbacks(action);
15885                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15886                        Choreographer.CALLBACK_ANIMATION, action, null);
15887            }
15888            getRunQueue().removeCallbacks(action);
15889        }
15890        return true;
15891    }
15892
15893    /**
15894     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15895     * Use this to invalidate the View from a non-UI thread.</p>
15896     *
15897     * <p>This method can be invoked from outside of the UI thread
15898     * only when this View is attached to a window.</p>
15899     *
15900     * @see #invalidate()
15901     * @see #postInvalidateDelayed(long)
15902     */
15903    public void postInvalidate() {
15904        postInvalidateDelayed(0);
15905    }
15906
15907    /**
15908     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15909     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15910     *
15911     * <p>This method can be invoked from outside of the UI thread
15912     * only when this View is attached to a window.</p>
15913     *
15914     * @param left The left coordinate of the rectangle to invalidate.
15915     * @param top The top coordinate of the rectangle to invalidate.
15916     * @param right The right coordinate of the rectangle to invalidate.
15917     * @param bottom The bottom coordinate of the rectangle to invalidate.
15918     *
15919     * @see #invalidate(int, int, int, int)
15920     * @see #invalidate(Rect)
15921     * @see #postInvalidateDelayed(long, int, int, int, int)
15922     */
15923    public void postInvalidate(int left, int top, int right, int bottom) {
15924        postInvalidateDelayed(0, left, top, right, bottom);
15925    }
15926
15927    /**
15928     * <p>Cause an invalidate to happen on a subsequent cycle through the event
15929     * loop. Waits for the specified amount of time.</p>
15930     *
15931     * <p>This method can be invoked from outside of the UI thread
15932     * only when this View is attached to a window.</p>
15933     *
15934     * @param delayMilliseconds the duration in milliseconds to delay the
15935     *         invalidation by
15936     *
15937     * @see #invalidate()
15938     * @see #postInvalidate()
15939     */
15940    public void postInvalidateDelayed(long delayMilliseconds) {
15941        // We try only with the AttachInfo because there's no point in invalidating
15942        // if we are not attached to our window
15943        final AttachInfo attachInfo = mAttachInfo;
15944        if (attachInfo != null) {
15945            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15946        }
15947    }
15948
15949    /**
15950     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15951     * through the event loop. Waits for the specified amount of time.</p>
15952     *
15953     * <p>This method can be invoked from outside of the UI thread
15954     * only when this View is attached to a window.</p>
15955     *
15956     * @param delayMilliseconds the duration in milliseconds to delay the
15957     *         invalidation by
15958     * @param left The left coordinate of the rectangle to invalidate.
15959     * @param top The top coordinate of the rectangle to invalidate.
15960     * @param right The right coordinate of the rectangle to invalidate.
15961     * @param bottom The bottom coordinate of the rectangle to invalidate.
15962     *
15963     * @see #invalidate(int, int, int, int)
15964     * @see #invalidate(Rect)
15965     * @see #postInvalidate(int, int, int, int)
15966     */
15967    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15968            int right, int bottom) {
15969
15970        // We try only with the AttachInfo because there's no point in invalidating
15971        // if we are not attached to our window
15972        final AttachInfo attachInfo = mAttachInfo;
15973        if (attachInfo != null) {
15974            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15975            info.target = this;
15976            info.left = left;
15977            info.top = top;
15978            info.right = right;
15979            info.bottom = bottom;
15980
15981            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15982        }
15983    }
15984
15985    /**
15986     * <p>Cause an invalidate to happen on the next animation time step, typically the
15987     * next display frame.</p>
15988     *
15989     * <p>This method can be invoked from outside of the UI thread
15990     * only when this View is attached to a window.</p>
15991     *
15992     * @see #invalidate()
15993     */
15994    public void postInvalidateOnAnimation() {
15995        // We try only with the AttachInfo because there's no point in invalidating
15996        // if we are not attached to our window
15997        final AttachInfo attachInfo = mAttachInfo;
15998        if (attachInfo != null) {
15999            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
16000        }
16001    }
16002
16003    /**
16004     * <p>Cause an invalidate of the specified area to happen on the next animation
16005     * time step, typically the next display frame.</p>
16006     *
16007     * <p>This method can be invoked from outside of the UI thread
16008     * only when this View is attached to a window.</p>
16009     *
16010     * @param left The left coordinate of the rectangle to invalidate.
16011     * @param top The top coordinate of the rectangle to invalidate.
16012     * @param right The right coordinate of the rectangle to invalidate.
16013     * @param bottom The bottom coordinate of the rectangle to invalidate.
16014     *
16015     * @see #invalidate(int, int, int, int)
16016     * @see #invalidate(Rect)
16017     */
16018    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
16019        // We try only with the AttachInfo because there's no point in invalidating
16020        // if we are not attached to our window
16021        final AttachInfo attachInfo = mAttachInfo;
16022        if (attachInfo != null) {
16023            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
16024            info.target = this;
16025            info.left = left;
16026            info.top = top;
16027            info.right = right;
16028            info.bottom = bottom;
16029
16030            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
16031        }
16032    }
16033
16034    /**
16035     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
16036     * This event is sent at most once every
16037     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
16038     */
16039    private void postSendViewScrolledAccessibilityEventCallback() {
16040        if (mSendViewScrolledAccessibilityEvent == null) {
16041            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
16042        }
16043        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
16044            mSendViewScrolledAccessibilityEvent.mIsPending = true;
16045            postDelayed(mSendViewScrolledAccessibilityEvent,
16046                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
16047        }
16048    }
16049
16050    /**
16051     * Called by a parent to request that a child update its values for mScrollX
16052     * and mScrollY if necessary. This will typically be done if the child is
16053     * animating a scroll using a {@link android.widget.Scroller Scroller}
16054     * object.
16055     */
16056    public void computeScroll() {
16057    }
16058
16059    /**
16060     * <p>Indicate whether the horizontal edges are faded when the view is
16061     * scrolled horizontally.</p>
16062     *
16063     * @return true if the horizontal edges should are faded on scroll, false
16064     *         otherwise
16065     *
16066     * @see #setHorizontalFadingEdgeEnabled(boolean)
16067     *
16068     * @attr ref android.R.styleable#View_requiresFadingEdge
16069     */
16070    public boolean isHorizontalFadingEdgeEnabled() {
16071        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
16072    }
16073
16074    /**
16075     * <p>Define whether the horizontal edges should be faded when this view
16076     * is scrolled horizontally.</p>
16077     *
16078     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
16079     *                                    be faded when the view is scrolled
16080     *                                    horizontally
16081     *
16082     * @see #isHorizontalFadingEdgeEnabled()
16083     *
16084     * @attr ref android.R.styleable#View_requiresFadingEdge
16085     */
16086    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
16087        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
16088            if (horizontalFadingEdgeEnabled) {
16089                initScrollCache();
16090            }
16091
16092            mViewFlags ^= FADING_EDGE_HORIZONTAL;
16093        }
16094    }
16095
16096    /**
16097     * <p>Indicate whether the vertical edges are faded when the view is
16098     * scrolled horizontally.</p>
16099     *
16100     * @return true if the vertical edges should are faded on scroll, false
16101     *         otherwise
16102     *
16103     * @see #setVerticalFadingEdgeEnabled(boolean)
16104     *
16105     * @attr ref android.R.styleable#View_requiresFadingEdge
16106     */
16107    public boolean isVerticalFadingEdgeEnabled() {
16108        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
16109    }
16110
16111    /**
16112     * <p>Define whether the vertical edges should be faded when this view
16113     * is scrolled vertically.</p>
16114     *
16115     * @param verticalFadingEdgeEnabled true if the vertical edges should
16116     *                                  be faded when the view is scrolled
16117     *                                  vertically
16118     *
16119     * @see #isVerticalFadingEdgeEnabled()
16120     *
16121     * @attr ref android.R.styleable#View_requiresFadingEdge
16122     */
16123    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
16124        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
16125            if (verticalFadingEdgeEnabled) {
16126                initScrollCache();
16127            }
16128
16129            mViewFlags ^= FADING_EDGE_VERTICAL;
16130        }
16131    }
16132
16133    /**
16134     * Returns the strength, or intensity, of the top faded edge. The strength is
16135     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16136     * returns 0.0 or 1.0 but no value in between.
16137     *
16138     * Subclasses should override this method to provide a smoother fade transition
16139     * when scrolling occurs.
16140     *
16141     * @return the intensity of the top fade as a float between 0.0f and 1.0f
16142     */
16143    protected float getTopFadingEdgeStrength() {
16144        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
16145    }
16146
16147    /**
16148     * Returns the strength, or intensity, of the bottom faded edge. The strength is
16149     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16150     * returns 0.0 or 1.0 but no value in between.
16151     *
16152     * Subclasses should override this method to provide a smoother fade transition
16153     * when scrolling occurs.
16154     *
16155     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
16156     */
16157    protected float getBottomFadingEdgeStrength() {
16158        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
16159                computeVerticalScrollRange() ? 1.0f : 0.0f;
16160    }
16161
16162    /**
16163     * Returns the strength, or intensity, of the left faded edge. The strength is
16164     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16165     * returns 0.0 or 1.0 but no value in between.
16166     *
16167     * Subclasses should override this method to provide a smoother fade transition
16168     * when scrolling occurs.
16169     *
16170     * @return the intensity of the left fade as a float between 0.0f and 1.0f
16171     */
16172    protected float getLeftFadingEdgeStrength() {
16173        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
16174    }
16175
16176    /**
16177     * Returns the strength, or intensity, of the right faded edge. The strength is
16178     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16179     * returns 0.0 or 1.0 but no value in between.
16180     *
16181     * Subclasses should override this method to provide a smoother fade transition
16182     * when scrolling occurs.
16183     *
16184     * @return the intensity of the right fade as a float between 0.0f and 1.0f
16185     */
16186    protected float getRightFadingEdgeStrength() {
16187        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
16188                computeHorizontalScrollRange() ? 1.0f : 0.0f;
16189    }
16190
16191    /**
16192     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
16193     * scrollbar is not drawn by default.</p>
16194     *
16195     * @return true if the horizontal scrollbar should be painted, false
16196     *         otherwise
16197     *
16198     * @see #setHorizontalScrollBarEnabled(boolean)
16199     */
16200    public boolean isHorizontalScrollBarEnabled() {
16201        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
16202    }
16203
16204    /**
16205     * <p>Define whether the horizontal scrollbar should be drawn or not. The
16206     * scrollbar is not drawn by default.</p>
16207     *
16208     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
16209     *                                   be painted
16210     *
16211     * @see #isHorizontalScrollBarEnabled()
16212     */
16213    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
16214        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
16215            mViewFlags ^= SCROLLBARS_HORIZONTAL;
16216            computeOpaqueFlags();
16217            resolvePadding();
16218        }
16219    }
16220
16221    /**
16222     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
16223     * scrollbar is not drawn by default.</p>
16224     *
16225     * @return true if the vertical scrollbar should be painted, false
16226     *         otherwise
16227     *
16228     * @see #setVerticalScrollBarEnabled(boolean)
16229     */
16230    public boolean isVerticalScrollBarEnabled() {
16231        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
16232    }
16233
16234    /**
16235     * <p>Define whether the vertical scrollbar should be drawn or not. The
16236     * scrollbar is not drawn by default.</p>
16237     *
16238     * @param verticalScrollBarEnabled true if the vertical scrollbar should
16239     *                                 be painted
16240     *
16241     * @see #isVerticalScrollBarEnabled()
16242     */
16243    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
16244        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
16245            mViewFlags ^= SCROLLBARS_VERTICAL;
16246            computeOpaqueFlags();
16247            resolvePadding();
16248        }
16249    }
16250
16251    /**
16252     * @hide
16253     */
16254    protected void recomputePadding() {
16255        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16256    }
16257
16258    /**
16259     * Define whether scrollbars will fade when the view is not scrolling.
16260     *
16261     * @param fadeScrollbars whether to enable fading
16262     *
16263     * @attr ref android.R.styleable#View_fadeScrollbars
16264     */
16265    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
16266        initScrollCache();
16267        final ScrollabilityCache scrollabilityCache = mScrollCache;
16268        scrollabilityCache.fadeScrollBars = fadeScrollbars;
16269        if (fadeScrollbars) {
16270            scrollabilityCache.state = ScrollabilityCache.OFF;
16271        } else {
16272            scrollabilityCache.state = ScrollabilityCache.ON;
16273        }
16274    }
16275
16276    /**
16277     *
16278     * Returns true if scrollbars will fade when this view is not scrolling
16279     *
16280     * @return true if scrollbar fading is enabled
16281     *
16282     * @attr ref android.R.styleable#View_fadeScrollbars
16283     */
16284    public boolean isScrollbarFadingEnabled() {
16285        return mScrollCache != null && mScrollCache.fadeScrollBars;
16286    }
16287
16288    /**
16289     *
16290     * Returns the delay before scrollbars fade.
16291     *
16292     * @return the delay before scrollbars fade
16293     *
16294     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16295     */
16296    public int getScrollBarDefaultDelayBeforeFade() {
16297        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
16298                mScrollCache.scrollBarDefaultDelayBeforeFade;
16299    }
16300
16301    /**
16302     * Define the delay before scrollbars fade.
16303     *
16304     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
16305     *
16306     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16307     */
16308    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
16309        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
16310    }
16311
16312    /**
16313     *
16314     * Returns the scrollbar fade duration.
16315     *
16316     * @return the scrollbar fade duration, in milliseconds
16317     *
16318     * @attr ref android.R.styleable#View_scrollbarFadeDuration
16319     */
16320    public int getScrollBarFadeDuration() {
16321        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
16322                mScrollCache.scrollBarFadeDuration;
16323    }
16324
16325    /**
16326     * Define the scrollbar fade duration.
16327     *
16328     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
16329     *
16330     * @attr ref android.R.styleable#View_scrollbarFadeDuration
16331     */
16332    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
16333        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
16334    }
16335
16336    /**
16337     *
16338     * Returns the scrollbar size.
16339     *
16340     * @return the scrollbar size
16341     *
16342     * @attr ref android.R.styleable#View_scrollbarSize
16343     */
16344    public int getScrollBarSize() {
16345        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
16346                mScrollCache.scrollBarSize;
16347    }
16348
16349    /**
16350     * Define the scrollbar size.
16351     *
16352     * @param scrollBarSize - the scrollbar size
16353     *
16354     * @attr ref android.R.styleable#View_scrollbarSize
16355     */
16356    public void setScrollBarSize(int scrollBarSize) {
16357        getScrollCache().scrollBarSize = scrollBarSize;
16358    }
16359
16360    /**
16361     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
16362     * inset. When inset, they add to the padding of the view. And the scrollbars
16363     * can be drawn inside the padding area or on the edge of the view. For example,
16364     * if a view has a background drawable and you want to draw the scrollbars
16365     * inside the padding specified by the drawable, you can use
16366     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
16367     * appear at the edge of the view, ignoring the padding, then you can use
16368     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
16369     * @param style the style of the scrollbars. Should be one of
16370     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
16371     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
16372     * @see #SCROLLBARS_INSIDE_OVERLAY
16373     * @see #SCROLLBARS_INSIDE_INSET
16374     * @see #SCROLLBARS_OUTSIDE_OVERLAY
16375     * @see #SCROLLBARS_OUTSIDE_INSET
16376     *
16377     * @attr ref android.R.styleable#View_scrollbarStyle
16378     */
16379    public void setScrollBarStyle(@ScrollBarStyle int style) {
16380        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
16381            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
16382            computeOpaqueFlags();
16383            resolvePadding();
16384        }
16385    }
16386
16387    /**
16388     * <p>Returns the current scrollbar style.</p>
16389     * @return the current scrollbar style
16390     * @see #SCROLLBARS_INSIDE_OVERLAY
16391     * @see #SCROLLBARS_INSIDE_INSET
16392     * @see #SCROLLBARS_OUTSIDE_OVERLAY
16393     * @see #SCROLLBARS_OUTSIDE_INSET
16394     *
16395     * @attr ref android.R.styleable#View_scrollbarStyle
16396     */
16397    @ViewDebug.ExportedProperty(mapping = {
16398            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
16399            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
16400            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
16401            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
16402    })
16403    @ScrollBarStyle
16404    public int getScrollBarStyle() {
16405        return mViewFlags & SCROLLBARS_STYLE_MASK;
16406    }
16407
16408    /**
16409     * <p>Compute the horizontal range that the horizontal scrollbar
16410     * represents.</p>
16411     *
16412     * <p>The range is expressed in arbitrary units that must be the same as the
16413     * units used by {@link #computeHorizontalScrollExtent()} and
16414     * {@link #computeHorizontalScrollOffset()}.</p>
16415     *
16416     * <p>The default range is the drawing width of this view.</p>
16417     *
16418     * @return the total horizontal range represented by the horizontal
16419     *         scrollbar
16420     *
16421     * @see #computeHorizontalScrollExtent()
16422     * @see #computeHorizontalScrollOffset()
16423     * @see android.widget.ScrollBarDrawable
16424     */
16425    protected int computeHorizontalScrollRange() {
16426        return getWidth();
16427    }
16428
16429    /**
16430     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
16431     * within the horizontal range. This value is used to compute the position
16432     * of the thumb within the scrollbar's track.</p>
16433     *
16434     * <p>The range is expressed in arbitrary units that must be the same as the
16435     * units used by {@link #computeHorizontalScrollRange()} and
16436     * {@link #computeHorizontalScrollExtent()}.</p>
16437     *
16438     * <p>The default offset is the scroll offset of this view.</p>
16439     *
16440     * @return the horizontal offset of the scrollbar's thumb
16441     *
16442     * @see #computeHorizontalScrollRange()
16443     * @see #computeHorizontalScrollExtent()
16444     * @see android.widget.ScrollBarDrawable
16445     */
16446    protected int computeHorizontalScrollOffset() {
16447        return mScrollX;
16448    }
16449
16450    /**
16451     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
16452     * within the horizontal range. This value is used to compute the length
16453     * of the thumb within the scrollbar's track.</p>
16454     *
16455     * <p>The range is expressed in arbitrary units that must be the same as the
16456     * units used by {@link #computeHorizontalScrollRange()} and
16457     * {@link #computeHorizontalScrollOffset()}.</p>
16458     *
16459     * <p>The default extent is the drawing width of this view.</p>
16460     *
16461     * @return the horizontal extent of the scrollbar's thumb
16462     *
16463     * @see #computeHorizontalScrollRange()
16464     * @see #computeHorizontalScrollOffset()
16465     * @see android.widget.ScrollBarDrawable
16466     */
16467    protected int computeHorizontalScrollExtent() {
16468        return getWidth();
16469    }
16470
16471    /**
16472     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
16473     *
16474     * <p>The range is expressed in arbitrary units that must be the same as the
16475     * units used by {@link #computeVerticalScrollExtent()} and
16476     * {@link #computeVerticalScrollOffset()}.</p>
16477     *
16478     * @return the total vertical range represented by the vertical scrollbar
16479     *
16480     * <p>The default range is the drawing height of this view.</p>
16481     *
16482     * @see #computeVerticalScrollExtent()
16483     * @see #computeVerticalScrollOffset()
16484     * @see android.widget.ScrollBarDrawable
16485     */
16486    protected int computeVerticalScrollRange() {
16487        return getHeight();
16488    }
16489
16490    /**
16491     * <p>Compute the vertical offset of the vertical scrollbar's thumb
16492     * within the horizontal range. This value is used to compute the position
16493     * of the thumb within the scrollbar's track.</p>
16494     *
16495     * <p>The range is expressed in arbitrary units that must be the same as the
16496     * units used by {@link #computeVerticalScrollRange()} and
16497     * {@link #computeVerticalScrollExtent()}.</p>
16498     *
16499     * <p>The default offset is the scroll offset of this view.</p>
16500     *
16501     * @return the vertical offset of the scrollbar's thumb
16502     *
16503     * @see #computeVerticalScrollRange()
16504     * @see #computeVerticalScrollExtent()
16505     * @see android.widget.ScrollBarDrawable
16506     */
16507    protected int computeVerticalScrollOffset() {
16508        return mScrollY;
16509    }
16510
16511    /**
16512     * <p>Compute the vertical extent of the vertical scrollbar's thumb
16513     * within the vertical range. This value is used to compute the length
16514     * of the thumb within the scrollbar's track.</p>
16515     *
16516     * <p>The range is expressed in arbitrary units that must be the same as the
16517     * units used by {@link #computeVerticalScrollRange()} and
16518     * {@link #computeVerticalScrollOffset()}.</p>
16519     *
16520     * <p>The default extent is the drawing height of this view.</p>
16521     *
16522     * @return the vertical extent of the scrollbar's thumb
16523     *
16524     * @see #computeVerticalScrollRange()
16525     * @see #computeVerticalScrollOffset()
16526     * @see android.widget.ScrollBarDrawable
16527     */
16528    protected int computeVerticalScrollExtent() {
16529        return getHeight();
16530    }
16531
16532    /**
16533     * Check if this view can be scrolled horizontally in a certain direction.
16534     *
16535     * @param direction Negative to check scrolling left, positive to check scrolling right.
16536     * @return true if this view can be scrolled in the specified direction, false otherwise.
16537     */
16538    public boolean canScrollHorizontally(int direction) {
16539        final int offset = computeHorizontalScrollOffset();
16540        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
16541        if (range == 0) return false;
16542        if (direction < 0) {
16543            return offset > 0;
16544        } else {
16545            return offset < range - 1;
16546        }
16547    }
16548
16549    /**
16550     * Check if this view can be scrolled vertically in a certain direction.
16551     *
16552     * @param direction Negative to check scrolling up, positive to check scrolling down.
16553     * @return true if this view can be scrolled in the specified direction, false otherwise.
16554     */
16555    public boolean canScrollVertically(int direction) {
16556        final int offset = computeVerticalScrollOffset();
16557        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16558        if (range == 0) return false;
16559        if (direction < 0) {
16560            return offset > 0;
16561        } else {
16562            return offset < range - 1;
16563        }
16564    }
16565
16566    void getScrollIndicatorBounds(@NonNull Rect out) {
16567        out.left = mScrollX;
16568        out.right = mScrollX + mRight - mLeft;
16569        out.top = mScrollY;
16570        out.bottom = mScrollY + mBottom - mTop;
16571    }
16572
16573    private void onDrawScrollIndicators(Canvas c) {
16574        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16575            // No scroll indicators enabled.
16576            return;
16577        }
16578
16579        final Drawable dr = mScrollIndicatorDrawable;
16580        if (dr == null) {
16581            // Scroll indicators aren't supported here.
16582            return;
16583        }
16584
16585        final int h = dr.getIntrinsicHeight();
16586        final int w = dr.getIntrinsicWidth();
16587        final Rect rect = mAttachInfo.mTmpInvalRect;
16588        getScrollIndicatorBounds(rect);
16589
16590        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16591            final boolean canScrollUp = canScrollVertically(-1);
16592            if (canScrollUp) {
16593                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16594                dr.draw(c);
16595            }
16596        }
16597
16598        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16599            final boolean canScrollDown = canScrollVertically(1);
16600            if (canScrollDown) {
16601                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16602                dr.draw(c);
16603            }
16604        }
16605
16606        final int leftRtl;
16607        final int rightRtl;
16608        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16609            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16610            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16611        } else {
16612            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16613            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16614        }
16615
16616        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16617        if ((mPrivateFlags3 & leftMask) != 0) {
16618            final boolean canScrollLeft = canScrollHorizontally(-1);
16619            if (canScrollLeft) {
16620                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16621                dr.draw(c);
16622            }
16623        }
16624
16625        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16626        if ((mPrivateFlags3 & rightMask) != 0) {
16627            final boolean canScrollRight = canScrollHorizontally(1);
16628            if (canScrollRight) {
16629                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16630                dr.draw(c);
16631            }
16632        }
16633    }
16634
16635    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16636            @Nullable Rect touchBounds) {
16637        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16638        if (bounds == null) {
16639            return;
16640        }
16641        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16642        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16643                && !isVerticalScrollBarHidden();
16644        final int size = getHorizontalScrollbarHeight();
16645        final int verticalScrollBarGap = drawVerticalScrollBar ?
16646                getVerticalScrollbarWidth() : 0;
16647        final int width = mRight - mLeft;
16648        final int height = mBottom - mTop;
16649        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16650        bounds.left = mScrollX + (mPaddingLeft & inside);
16651        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16652        bounds.bottom = bounds.top + size;
16653
16654        if (touchBounds == null) {
16655            return;
16656        }
16657        if (touchBounds != bounds) {
16658            touchBounds.set(bounds);
16659        }
16660        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16661        if (touchBounds.height() < minTouchTarget) {
16662            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16663            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16664            touchBounds.top = touchBounds.bottom - minTouchTarget;
16665        }
16666        if (touchBounds.width() < minTouchTarget) {
16667            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16668            touchBounds.left -= adjust;
16669            touchBounds.right = touchBounds.left + minTouchTarget;
16670        }
16671    }
16672
16673    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16674        if (mRoundScrollbarRenderer == null) {
16675            getStraightVerticalScrollBarBounds(bounds, touchBounds);
16676        } else {
16677            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16678        }
16679    }
16680
16681    private void getRoundVerticalScrollBarBounds(Rect bounds) {
16682        final int width = mRight - mLeft;
16683        final int height = mBottom - mTop;
16684        // Do not take padding into account as we always want the scrollbars
16685        // to hug the screen for round wearable devices.
16686        bounds.left = mScrollX;
16687        bounds.top = mScrollY;
16688        bounds.right = bounds.left + width;
16689        bounds.bottom = mScrollY + height;
16690    }
16691
16692    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16693            @Nullable Rect touchBounds) {
16694        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16695        if (bounds == null) {
16696            return;
16697        }
16698        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16699        final int size = getVerticalScrollbarWidth();
16700        int verticalScrollbarPosition = mVerticalScrollbarPosition;
16701        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16702            verticalScrollbarPosition = isLayoutRtl() ?
16703                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16704        }
16705        final int width = mRight - mLeft;
16706        final int height = mBottom - mTop;
16707        switch (verticalScrollbarPosition) {
16708            default:
16709            case SCROLLBAR_POSITION_RIGHT:
16710                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16711                break;
16712            case SCROLLBAR_POSITION_LEFT:
16713                bounds.left = mScrollX + (mUserPaddingLeft & inside);
16714                break;
16715        }
16716        bounds.top = mScrollY + (mPaddingTop & inside);
16717        bounds.right = bounds.left + size;
16718        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16719
16720        if (touchBounds == null) {
16721            return;
16722        }
16723        if (touchBounds != bounds) {
16724            touchBounds.set(bounds);
16725        }
16726        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16727        if (touchBounds.width() < minTouchTarget) {
16728            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16729            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16730                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16731                touchBounds.left = touchBounds.right - minTouchTarget;
16732            } else {
16733                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16734                touchBounds.right = touchBounds.left + minTouchTarget;
16735            }
16736        }
16737        if (touchBounds.height() < minTouchTarget) {
16738            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16739            touchBounds.top -= adjust;
16740            touchBounds.bottom = touchBounds.top + minTouchTarget;
16741        }
16742    }
16743
16744    /**
16745     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16746     * scrollbars are painted only if they have been awakened first.</p>
16747     *
16748     * @param canvas the canvas on which to draw the scrollbars
16749     *
16750     * @see #awakenScrollBars(int)
16751     */
16752    protected final void onDrawScrollBars(Canvas canvas) {
16753        // scrollbars are drawn only when the animation is running
16754        final ScrollabilityCache cache = mScrollCache;
16755
16756        if (cache != null) {
16757
16758            int state = cache.state;
16759
16760            if (state == ScrollabilityCache.OFF) {
16761                return;
16762            }
16763
16764            boolean invalidate = false;
16765
16766            if (state == ScrollabilityCache.FADING) {
16767                // We're fading -- get our fade interpolation
16768                if (cache.interpolatorValues == null) {
16769                    cache.interpolatorValues = new float[1];
16770                }
16771
16772                float[] values = cache.interpolatorValues;
16773
16774                // Stops the animation if we're done
16775                if (cache.scrollBarInterpolator.timeToValues(values) ==
16776                        Interpolator.Result.FREEZE_END) {
16777                    cache.state = ScrollabilityCache.OFF;
16778                } else {
16779                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16780                }
16781
16782                // This will make the scroll bars inval themselves after
16783                // drawing. We only want this when we're fading so that
16784                // we prevent excessive redraws
16785                invalidate = true;
16786            } else {
16787                // We're just on -- but we may have been fading before so
16788                // reset alpha
16789                cache.scrollBar.mutate().setAlpha(255);
16790            }
16791
16792            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16793            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16794                    && !isVerticalScrollBarHidden();
16795
16796            // Fork out the scroll bar drawing for round wearable devices.
16797            if (mRoundScrollbarRenderer != null) {
16798                if (drawVerticalScrollBar) {
16799                    final Rect bounds = cache.mScrollBarBounds;
16800                    getVerticalScrollBarBounds(bounds, null);
16801                    mRoundScrollbarRenderer.drawRoundScrollbars(
16802                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16803                    if (invalidate) {
16804                        invalidate();
16805                    }
16806                }
16807                // Do not draw horizontal scroll bars for round wearable devices.
16808            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16809                final ScrollBarDrawable scrollBar = cache.scrollBar;
16810
16811                if (drawHorizontalScrollBar) {
16812                    scrollBar.setParameters(computeHorizontalScrollRange(),
16813                            computeHorizontalScrollOffset(),
16814                            computeHorizontalScrollExtent(), false);
16815                    final Rect bounds = cache.mScrollBarBounds;
16816                    getHorizontalScrollBarBounds(bounds, null);
16817                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16818                            bounds.right, bounds.bottom);
16819                    if (invalidate) {
16820                        invalidate(bounds);
16821                    }
16822                }
16823
16824                if (drawVerticalScrollBar) {
16825                    scrollBar.setParameters(computeVerticalScrollRange(),
16826                            computeVerticalScrollOffset(),
16827                            computeVerticalScrollExtent(), true);
16828                    final Rect bounds = cache.mScrollBarBounds;
16829                    getVerticalScrollBarBounds(bounds, null);
16830                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16831                            bounds.right, bounds.bottom);
16832                    if (invalidate) {
16833                        invalidate(bounds);
16834                    }
16835                }
16836            }
16837        }
16838    }
16839
16840    /**
16841     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16842     * FastScroller is visible.
16843     * @return whether to temporarily hide the vertical scrollbar
16844     * @hide
16845     */
16846    protected boolean isVerticalScrollBarHidden() {
16847        return false;
16848    }
16849
16850    /**
16851     * <p>Draw the horizontal scrollbar if
16852     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16853     *
16854     * @param canvas the canvas on which to draw the scrollbar
16855     * @param scrollBar the scrollbar's drawable
16856     *
16857     * @see #isHorizontalScrollBarEnabled()
16858     * @see #computeHorizontalScrollRange()
16859     * @see #computeHorizontalScrollExtent()
16860     * @see #computeHorizontalScrollOffset()
16861     * @see android.widget.ScrollBarDrawable
16862     * @hide
16863     */
16864    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16865            int l, int t, int r, int b) {
16866        scrollBar.setBounds(l, t, r, b);
16867        scrollBar.draw(canvas);
16868    }
16869
16870    /**
16871     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16872     * returns true.</p>
16873     *
16874     * @param canvas the canvas on which to draw the scrollbar
16875     * @param scrollBar the scrollbar's drawable
16876     *
16877     * @see #isVerticalScrollBarEnabled()
16878     * @see #computeVerticalScrollRange()
16879     * @see #computeVerticalScrollExtent()
16880     * @see #computeVerticalScrollOffset()
16881     * @see android.widget.ScrollBarDrawable
16882     * @hide
16883     */
16884    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16885            int l, int t, int r, int b) {
16886        scrollBar.setBounds(l, t, r, b);
16887        scrollBar.draw(canvas);
16888    }
16889
16890    /**
16891     * Implement this to do your drawing.
16892     *
16893     * @param canvas the canvas on which the background will be drawn
16894     */
16895    protected void onDraw(Canvas canvas) {
16896    }
16897
16898    /*
16899     * Caller is responsible for calling requestLayout if necessary.
16900     * (This allows addViewInLayout to not request a new layout.)
16901     */
16902    void assignParent(ViewParent parent) {
16903        if (mParent == null) {
16904            mParent = parent;
16905        } else if (parent == null) {
16906            mParent = null;
16907        } else {
16908            throw new RuntimeException("view " + this + " being added, but"
16909                    + " it already has a parent");
16910        }
16911    }
16912
16913    /**
16914     * This is called when the view is attached to a window.  At this point it
16915     * has a Surface and will start drawing.  Note that this function is
16916     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16917     * however it may be called any time before the first onDraw -- including
16918     * before or after {@link #onMeasure(int, int)}.
16919     *
16920     * @see #onDetachedFromWindow()
16921     */
16922    @CallSuper
16923    protected void onAttachedToWindow() {
16924        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16925            mParent.requestTransparentRegion(this);
16926        }
16927
16928        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16929
16930        jumpDrawablesToCurrentState();
16931
16932        resetSubtreeAccessibilityStateChanged();
16933
16934        // rebuild, since Outline not maintained while View is detached
16935        rebuildOutline();
16936
16937        if (isFocused()) {
16938            InputMethodManager imm = InputMethodManager.peekInstance();
16939            if (imm != null) {
16940                imm.focusIn(this);
16941            }
16942        }
16943    }
16944
16945    /**
16946     * Resolve all RTL related properties.
16947     *
16948     * @return true if resolution of RTL properties has been done
16949     *
16950     * @hide
16951     */
16952    public boolean resolveRtlPropertiesIfNeeded() {
16953        if (!needRtlPropertiesResolution()) return false;
16954
16955        // Order is important here: LayoutDirection MUST be resolved first
16956        if (!isLayoutDirectionResolved()) {
16957            resolveLayoutDirection();
16958            resolveLayoutParams();
16959        }
16960        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16961        if (!isTextDirectionResolved()) {
16962            resolveTextDirection();
16963        }
16964        if (!isTextAlignmentResolved()) {
16965            resolveTextAlignment();
16966        }
16967        // Should resolve Drawables before Padding because we need the layout direction of the
16968        // Drawable to correctly resolve Padding.
16969        if (!areDrawablesResolved()) {
16970            resolveDrawables();
16971        }
16972        if (!isPaddingResolved()) {
16973            resolvePadding();
16974        }
16975        onRtlPropertiesChanged(getLayoutDirection());
16976        return true;
16977    }
16978
16979    /**
16980     * Reset resolution of all RTL related properties.
16981     *
16982     * @hide
16983     */
16984    public void resetRtlProperties() {
16985        resetResolvedLayoutDirection();
16986        resetResolvedTextDirection();
16987        resetResolvedTextAlignment();
16988        resetResolvedPadding();
16989        resetResolvedDrawables();
16990    }
16991
16992    /**
16993     * @see #onScreenStateChanged(int)
16994     */
16995    void dispatchScreenStateChanged(int screenState) {
16996        onScreenStateChanged(screenState);
16997    }
16998
16999    /**
17000     * This method is called whenever the state of the screen this view is
17001     * attached to changes. A state change will usually occurs when the screen
17002     * turns on or off (whether it happens automatically or the user does it
17003     * manually.)
17004     *
17005     * @param screenState The new state of the screen. Can be either
17006     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
17007     */
17008    public void onScreenStateChanged(int screenState) {
17009    }
17010
17011    /**
17012     * @see #onMovedToDisplay(int, Configuration)
17013     */
17014    void dispatchMovedToDisplay(Display display, Configuration config) {
17015        mAttachInfo.mDisplay = display;
17016        mAttachInfo.mDisplayState = display.getState();
17017        onMovedToDisplay(display.getDisplayId(), config);
17018    }
17019
17020    /**
17021     * Called by the system when the hosting activity is moved from one display to another without
17022     * recreation. This means that the activity is declared to handle all changes to configuration
17023     * that happened when it was switched to another display, so it wasn't destroyed and created
17024     * again.
17025     *
17026     * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
17027     * applied configuration actually changed. It is up to app developer to choose whether to handle
17028     * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
17029     * call.
17030     *
17031     * <p>Use this callback to track changes to the displays if some functionality relies on an
17032     * association with some display properties.
17033     *
17034     * @param displayId The id of the display to which the view was moved.
17035     * @param config Configuration of the resources on new display after move.
17036     *
17037     * @see #onConfigurationChanged(Configuration)
17038     * @hide
17039     */
17040    public void onMovedToDisplay(int displayId, Configuration config) {
17041    }
17042
17043    /**
17044     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
17045     */
17046    private boolean hasRtlSupport() {
17047        return mContext.getApplicationInfo().hasRtlSupport();
17048    }
17049
17050    /**
17051     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
17052     * RTL not supported)
17053     */
17054    private boolean isRtlCompatibilityMode() {
17055        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
17056        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
17057    }
17058
17059    /**
17060     * @return true if RTL properties need resolution.
17061     *
17062     */
17063    private boolean needRtlPropertiesResolution() {
17064        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
17065    }
17066
17067    /**
17068     * Called when any RTL property (layout direction or text direction or text alignment) has
17069     * been changed.
17070     *
17071     * Subclasses need to override this method to take care of cached information that depends on the
17072     * resolved layout direction, or to inform child views that inherit their layout direction.
17073     *
17074     * The default implementation does nothing.
17075     *
17076     * @param layoutDirection the direction of the layout
17077     *
17078     * @see #LAYOUT_DIRECTION_LTR
17079     * @see #LAYOUT_DIRECTION_RTL
17080     */
17081    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
17082    }
17083
17084    /**
17085     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
17086     * that the parent directionality can and will be resolved before its children.
17087     *
17088     * @return true if resolution has been done, false otherwise.
17089     *
17090     * @hide
17091     */
17092    public boolean resolveLayoutDirection() {
17093        // Clear any previous layout direction resolution
17094        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
17095
17096        if (hasRtlSupport()) {
17097            // Set resolved depending on layout direction
17098            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
17099                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
17100                case LAYOUT_DIRECTION_INHERIT:
17101                    // We cannot resolve yet. LTR is by default and let the resolution happen again
17102                    // later to get the correct resolved value
17103                    if (!canResolveLayoutDirection()) return false;
17104
17105                    // Parent has not yet resolved, LTR is still the default
17106                    try {
17107                        if (!mParent.isLayoutDirectionResolved()) return false;
17108
17109                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
17110                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17111                        }
17112                    } catch (AbstractMethodError e) {
17113                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
17114                                " does not fully implement ViewParent", e);
17115                    }
17116                    break;
17117                case LAYOUT_DIRECTION_RTL:
17118                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17119                    break;
17120                case LAYOUT_DIRECTION_LOCALE:
17121                    if((LAYOUT_DIRECTION_RTL ==
17122                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
17123                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17124                    }
17125                    break;
17126                default:
17127                    // Nothing to do, LTR by default
17128            }
17129        }
17130
17131        // Set to resolved
17132        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
17133        return true;
17134    }
17135
17136    /**
17137     * Check if layout direction resolution can be done.
17138     *
17139     * @return true if layout direction resolution can be done otherwise return false.
17140     */
17141    public boolean canResolveLayoutDirection() {
17142        switch (getRawLayoutDirection()) {
17143            case LAYOUT_DIRECTION_INHERIT:
17144                if (mParent != null) {
17145                    try {
17146                        return mParent.canResolveLayoutDirection();
17147                    } catch (AbstractMethodError e) {
17148                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
17149                                " does not fully implement ViewParent", e);
17150                    }
17151                }
17152                return false;
17153
17154            default:
17155                return true;
17156        }
17157    }
17158
17159    /**
17160     * Reset the resolved layout direction. Layout direction will be resolved during a call to
17161     * {@link #onMeasure(int, int)}.
17162     *
17163     * @hide
17164     */
17165    public void resetResolvedLayoutDirection() {
17166        // Reset the current resolved bits
17167        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
17168    }
17169
17170    /**
17171     * @return true if the layout direction is inherited.
17172     *
17173     * @hide
17174     */
17175    public boolean isLayoutDirectionInherited() {
17176        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
17177    }
17178
17179    /**
17180     * @return true if layout direction has been resolved.
17181     */
17182    public boolean isLayoutDirectionResolved() {
17183        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
17184    }
17185
17186    /**
17187     * Return if padding has been resolved
17188     *
17189     * @hide
17190     */
17191    boolean isPaddingResolved() {
17192        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
17193    }
17194
17195    /**
17196     * Resolves padding depending on layout direction, if applicable, and
17197     * recomputes internal padding values to adjust for scroll bars.
17198     *
17199     * @hide
17200     */
17201    public void resolvePadding() {
17202        final int resolvedLayoutDirection = getLayoutDirection();
17203
17204        if (!isRtlCompatibilityMode()) {
17205            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
17206            // If start / end padding are defined, they will be resolved (hence overriding) to
17207            // left / right or right / left depending on the resolved layout direction.
17208            // If start / end padding are not defined, use the left / right ones.
17209            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
17210                Rect padding = sThreadLocal.get();
17211                if (padding == null) {
17212                    padding = new Rect();
17213                    sThreadLocal.set(padding);
17214                }
17215                mBackground.getPadding(padding);
17216                if (!mLeftPaddingDefined) {
17217                    mUserPaddingLeftInitial = padding.left;
17218                }
17219                if (!mRightPaddingDefined) {
17220                    mUserPaddingRightInitial = padding.right;
17221                }
17222            }
17223            switch (resolvedLayoutDirection) {
17224                case LAYOUT_DIRECTION_RTL:
17225                    if (mUserPaddingStart != UNDEFINED_PADDING) {
17226                        mUserPaddingRight = mUserPaddingStart;
17227                    } else {
17228                        mUserPaddingRight = mUserPaddingRightInitial;
17229                    }
17230                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
17231                        mUserPaddingLeft = mUserPaddingEnd;
17232                    } else {
17233                        mUserPaddingLeft = mUserPaddingLeftInitial;
17234                    }
17235                    break;
17236                case LAYOUT_DIRECTION_LTR:
17237                default:
17238                    if (mUserPaddingStart != UNDEFINED_PADDING) {
17239                        mUserPaddingLeft = mUserPaddingStart;
17240                    } else {
17241                        mUserPaddingLeft = mUserPaddingLeftInitial;
17242                    }
17243                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
17244                        mUserPaddingRight = mUserPaddingEnd;
17245                    } else {
17246                        mUserPaddingRight = mUserPaddingRightInitial;
17247                    }
17248            }
17249
17250            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
17251        }
17252
17253        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
17254        onRtlPropertiesChanged(resolvedLayoutDirection);
17255
17256        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
17257    }
17258
17259    /**
17260     * Reset the resolved layout direction.
17261     *
17262     * @hide
17263     */
17264    public void resetResolvedPadding() {
17265        resetResolvedPaddingInternal();
17266    }
17267
17268    /**
17269     * Used when we only want to reset *this* view's padding and not trigger overrides
17270     * in ViewGroup that reset children too.
17271     */
17272    void resetResolvedPaddingInternal() {
17273        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
17274    }
17275
17276    /**
17277     * This is called when the view is detached from a window.  At this point it
17278     * no longer has a surface for drawing.
17279     *
17280     * @see #onAttachedToWindow()
17281     */
17282    @CallSuper
17283    protected void onDetachedFromWindow() {
17284    }
17285
17286    /**
17287     * This is a framework-internal mirror of onDetachedFromWindow() that's called
17288     * after onDetachedFromWindow().
17289     *
17290     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
17291     * The super method should be called at the end of the overridden method to ensure
17292     * subclasses are destroyed first
17293     *
17294     * @hide
17295     */
17296    @CallSuper
17297    protected void onDetachedFromWindowInternal() {
17298        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
17299        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
17300        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
17301
17302        removeUnsetPressCallback();
17303        removeLongPressCallback();
17304        removePerformClickCallback();
17305        removeSendViewScrolledAccessibilityEventCallback();
17306        stopNestedScroll();
17307
17308        // Anything that started animating right before detach should already
17309        // be in its final state when re-attached.
17310        jumpDrawablesToCurrentState();
17311
17312        destroyDrawingCache();
17313
17314        cleanupDraw();
17315        mCurrentAnimation = null;
17316
17317        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
17318            hideTooltip();
17319        }
17320    }
17321
17322    private void cleanupDraw() {
17323        resetDisplayList();
17324        if (mAttachInfo != null) {
17325            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
17326        }
17327    }
17328
17329    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
17330    }
17331
17332    /**
17333     * @return The number of times this view has been attached to a window
17334     */
17335    protected int getWindowAttachCount() {
17336        return mWindowAttachCount;
17337    }
17338
17339    /**
17340     * Retrieve a unique token identifying the window this view is attached to.
17341     * @return Return the window's token for use in
17342     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
17343     */
17344    public IBinder getWindowToken() {
17345        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
17346    }
17347
17348    /**
17349     * Retrieve the {@link WindowId} for the window this view is
17350     * currently attached to.
17351     */
17352    public WindowId getWindowId() {
17353        if (mAttachInfo == null) {
17354            return null;
17355        }
17356        if (mAttachInfo.mWindowId == null) {
17357            try {
17358                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
17359                        mAttachInfo.mWindowToken);
17360                mAttachInfo.mWindowId = new WindowId(
17361                        mAttachInfo.mIWindowId);
17362            } catch (RemoteException e) {
17363            }
17364        }
17365        return mAttachInfo.mWindowId;
17366    }
17367
17368    /**
17369     * Retrieve a unique token identifying the top-level "real" window of
17370     * the window that this view is attached to.  That is, this is like
17371     * {@link #getWindowToken}, except if the window this view in is a panel
17372     * window (attached to another containing window), then the token of
17373     * the containing window is returned instead.
17374     *
17375     * @return Returns the associated window token, either
17376     * {@link #getWindowToken()} or the containing window's token.
17377     */
17378    public IBinder getApplicationWindowToken() {
17379        AttachInfo ai = mAttachInfo;
17380        if (ai != null) {
17381            IBinder appWindowToken = ai.mPanelParentWindowToken;
17382            if (appWindowToken == null) {
17383                appWindowToken = ai.mWindowToken;
17384            }
17385            return appWindowToken;
17386        }
17387        return null;
17388    }
17389
17390    /**
17391     * Gets the logical display to which the view's window has been attached.
17392     *
17393     * @return The logical display, or null if the view is not currently attached to a window.
17394     */
17395    public Display getDisplay() {
17396        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
17397    }
17398
17399    /**
17400     * Retrieve private session object this view hierarchy is using to
17401     * communicate with the window manager.
17402     * @return the session object to communicate with the window manager
17403     */
17404    /*package*/ IWindowSession getWindowSession() {
17405        return mAttachInfo != null ? mAttachInfo.mSession : null;
17406    }
17407
17408    /**
17409     * Return the visibility value of the least visible component passed.
17410     */
17411    int combineVisibility(int vis1, int vis2) {
17412        // This works because VISIBLE < INVISIBLE < GONE.
17413        return Math.max(vis1, vis2);
17414    }
17415
17416    /**
17417     * @param info the {@link android.view.View.AttachInfo} to associated with
17418     *        this view
17419     */
17420    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
17421        mAttachInfo = info;
17422        if (mOverlay != null) {
17423            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
17424        }
17425        mWindowAttachCount++;
17426        // We will need to evaluate the drawable state at least once.
17427        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17428        if (mFloatingTreeObserver != null) {
17429            info.mTreeObserver.merge(mFloatingTreeObserver);
17430            mFloatingTreeObserver = null;
17431        }
17432
17433        registerPendingFrameMetricsObservers();
17434
17435        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
17436            mAttachInfo.mScrollContainers.add(this);
17437            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
17438        }
17439        // Transfer all pending runnables.
17440        if (mRunQueue != null) {
17441            mRunQueue.executeActions(info.mHandler);
17442            mRunQueue = null;
17443        }
17444        performCollectViewAttributes(mAttachInfo, visibility);
17445        onAttachedToWindow();
17446
17447        ListenerInfo li = mListenerInfo;
17448        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17449                li != null ? li.mOnAttachStateChangeListeners : null;
17450        if (listeners != null && listeners.size() > 0) {
17451            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17452            // perform the dispatching. The iterator is a safe guard against listeners that
17453            // could mutate the list by calling the various add/remove methods. This prevents
17454            // the array from being modified while we iterate it.
17455            for (OnAttachStateChangeListener listener : listeners) {
17456                listener.onViewAttachedToWindow(this);
17457            }
17458        }
17459
17460        int vis = info.mWindowVisibility;
17461        if (vis != GONE) {
17462            onWindowVisibilityChanged(vis);
17463            if (isShown()) {
17464                // Calling onVisibilityAggregated directly here since the subtree will also
17465                // receive dispatchAttachedToWindow and this same call
17466                onVisibilityAggregated(vis == VISIBLE);
17467            }
17468        }
17469
17470        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
17471        // As all views in the subtree will already receive dispatchAttachedToWindow
17472        // traversing the subtree again here is not desired.
17473        onVisibilityChanged(this, visibility);
17474
17475        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
17476            // If nobody has evaluated the drawable state yet, then do it now.
17477            refreshDrawableState();
17478        }
17479        needGlobalAttributesUpdate(false);
17480
17481        notifyEnterOrExitForAutoFillIfNeeded(true);
17482    }
17483
17484    void dispatchDetachedFromWindow() {
17485        AttachInfo info = mAttachInfo;
17486        if (info != null) {
17487            int vis = info.mWindowVisibility;
17488            if (vis != GONE) {
17489                onWindowVisibilityChanged(GONE);
17490                if (isShown()) {
17491                    // Invoking onVisibilityAggregated directly here since the subtree
17492                    // will also receive detached from window
17493                    onVisibilityAggregated(false);
17494                }
17495            }
17496        }
17497
17498        onDetachedFromWindow();
17499        onDetachedFromWindowInternal();
17500
17501        InputMethodManager imm = InputMethodManager.peekInstance();
17502        if (imm != null) {
17503            imm.onViewDetachedFromWindow(this);
17504        }
17505
17506        ListenerInfo li = mListenerInfo;
17507        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17508                li != null ? li.mOnAttachStateChangeListeners : null;
17509        if (listeners != null && listeners.size() > 0) {
17510            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17511            // perform the dispatching. The iterator is a safe guard against listeners that
17512            // could mutate the list by calling the various add/remove methods. This prevents
17513            // the array from being modified while we iterate it.
17514            for (OnAttachStateChangeListener listener : listeners) {
17515                listener.onViewDetachedFromWindow(this);
17516            }
17517        }
17518
17519        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
17520            mAttachInfo.mScrollContainers.remove(this);
17521            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
17522        }
17523
17524        mAttachInfo = null;
17525        if (mOverlay != null) {
17526            mOverlay.getOverlayView().dispatchDetachedFromWindow();
17527        }
17528
17529        notifyEnterOrExitForAutoFillIfNeeded(false);
17530    }
17531
17532    /**
17533     * Cancel any deferred high-level input events that were previously posted to the event queue.
17534     *
17535     * <p>Many views post high-level events such as click handlers to the event queue
17536     * to run deferred in order to preserve a desired user experience - clearing visible
17537     * pressed states before executing, etc. This method will abort any events of this nature
17538     * that are currently in flight.</p>
17539     *
17540     * <p>Custom views that generate their own high-level deferred input events should override
17541     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
17542     *
17543     * <p>This will also cancel pending input events for any child views.</p>
17544     *
17545     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
17546     * This will not impact newer events posted after this call that may occur as a result of
17547     * lower-level input events still waiting in the queue. If you are trying to prevent
17548     * double-submitted  events for the duration of some sort of asynchronous transaction
17549     * you should also take other steps to protect against unexpected double inputs e.g. calling
17550     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
17551     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
17552     */
17553    public final void cancelPendingInputEvents() {
17554        dispatchCancelPendingInputEvents();
17555    }
17556
17557    /**
17558     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17559     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17560     */
17561    void dispatchCancelPendingInputEvents() {
17562        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17563        onCancelPendingInputEvents();
17564        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17565            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17566                    " did not call through to super.onCancelPendingInputEvents()");
17567        }
17568    }
17569
17570    /**
17571     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17572     * a parent view.
17573     *
17574     * <p>This method is responsible for removing any pending high-level input events that were
17575     * posted to the event queue to run later. Custom view classes that post their own deferred
17576     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17577     * {@link android.os.Handler} should override this method, call
17578     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17579     * </p>
17580     */
17581    public void onCancelPendingInputEvents() {
17582        removePerformClickCallback();
17583        cancelLongPress();
17584        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17585    }
17586
17587    /**
17588     * Store this view hierarchy's frozen state into the given container.
17589     *
17590     * @param container The SparseArray in which to save the view's state.
17591     *
17592     * @see #restoreHierarchyState(android.util.SparseArray)
17593     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17594     * @see #onSaveInstanceState()
17595     */
17596    public void saveHierarchyState(SparseArray<Parcelable> container) {
17597        dispatchSaveInstanceState(container);
17598    }
17599
17600    /**
17601     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17602     * this view and its children. May be overridden to modify how freezing happens to a
17603     * view's children; for example, some views may want to not store state for their children.
17604     *
17605     * @param container The SparseArray in which to save the view's state.
17606     *
17607     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17608     * @see #saveHierarchyState(android.util.SparseArray)
17609     * @see #onSaveInstanceState()
17610     */
17611    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17612        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17613            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17614            Parcelable state = onSaveInstanceState();
17615            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17616                throw new IllegalStateException(
17617                        "Derived class did not call super.onSaveInstanceState()");
17618            }
17619            if (state != null) {
17620                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17621                // + ": " + state);
17622                container.put(mID, state);
17623            }
17624        }
17625    }
17626
17627    /**
17628     * Hook allowing a view to generate a representation of its internal state
17629     * that can later be used to create a new instance with that same state.
17630     * This state should only contain information that is not persistent or can
17631     * not be reconstructed later. For example, you will never store your
17632     * current position on screen because that will be computed again when a
17633     * new instance of the view is placed in its view hierarchy.
17634     * <p>
17635     * Some examples of things you may store here: the current cursor position
17636     * in a text view (but usually not the text itself since that is stored in a
17637     * content provider or other persistent storage), the currently selected
17638     * item in a list view.
17639     *
17640     * @return Returns a Parcelable object containing the view's current dynamic
17641     *         state, or null if there is nothing interesting to save.
17642     * @see #onRestoreInstanceState(Parcelable)
17643     * @see #saveHierarchyState(SparseArray)
17644     * @see #dispatchSaveInstanceState(SparseArray)
17645     * @see #setSaveEnabled(boolean)
17646     */
17647    @CallSuper
17648    @Nullable protected Parcelable onSaveInstanceState() {
17649        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17650        if (mStartActivityRequestWho != null || isAutofilled()
17651                || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
17652            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17653
17654            if (mStartActivityRequestWho != null) {
17655                state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
17656            }
17657
17658            if (isAutofilled()) {
17659                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
17660            }
17661
17662            if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
17663                state.mSavedData |= BaseSavedState.AUTOFILL_ID;
17664            }
17665
17666            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17667            state.mIsAutofilled = isAutofilled();
17668            state.mAutofillViewId = mAutofillViewId;
17669            return state;
17670        }
17671        return BaseSavedState.EMPTY_STATE;
17672    }
17673
17674    /**
17675     * Restore this view hierarchy's frozen state from the given container.
17676     *
17677     * @param container The SparseArray which holds previously frozen states.
17678     *
17679     * @see #saveHierarchyState(android.util.SparseArray)
17680     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17681     * @see #onRestoreInstanceState(android.os.Parcelable)
17682     */
17683    public void restoreHierarchyState(SparseArray<Parcelable> container) {
17684        dispatchRestoreInstanceState(container);
17685    }
17686
17687    /**
17688     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17689     * state for this view and its children. May be overridden to modify how restoring
17690     * happens to a view's children; for example, some views may want to not store state
17691     * for their children.
17692     *
17693     * @param container The SparseArray which holds previously saved state.
17694     *
17695     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17696     * @see #restoreHierarchyState(android.util.SparseArray)
17697     * @see #onRestoreInstanceState(android.os.Parcelable)
17698     */
17699    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17700        if (mID != NO_ID) {
17701            Parcelable state = container.get(mID);
17702            if (state != null) {
17703                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17704                // + ": " + state);
17705                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17706                onRestoreInstanceState(state);
17707                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17708                    throw new IllegalStateException(
17709                            "Derived class did not call super.onRestoreInstanceState()");
17710                }
17711            }
17712        }
17713    }
17714
17715    /**
17716     * Hook allowing a view to re-apply a representation of its internal state that had previously
17717     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17718     * null state.
17719     *
17720     * @param state The frozen state that had previously been returned by
17721     *        {@link #onSaveInstanceState}.
17722     *
17723     * @see #onSaveInstanceState()
17724     * @see #restoreHierarchyState(android.util.SparseArray)
17725     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17726     */
17727    @CallSuper
17728    protected void onRestoreInstanceState(Parcelable state) {
17729        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17730        if (state != null && !(state instanceof AbsSavedState)) {
17731            throw new IllegalArgumentException("Wrong state class, expecting View State but "
17732                    + "received " + state.getClass().toString() + " instead. This usually happens "
17733                    + "when two views of different type have the same id in the same hierarchy. "
17734                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17735                    + "other views do not use the same id.");
17736        }
17737        if (state != null && state instanceof BaseSavedState) {
17738            BaseSavedState baseState = (BaseSavedState) state;
17739
17740            if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
17741                mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
17742            }
17743            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
17744                setAutofilled(baseState.mIsAutofilled);
17745            }
17746            if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
17747                // It can happen that views have the same view id and the restoration path will not
17748                // be able to distinguish between them. The autofill id needs to be unique though.
17749                // Hence prevent the same autofill view id from being restored multiple times.
17750                ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID;
17751
17752                mAutofillViewId = baseState.mAutofillViewId;
17753            }
17754        }
17755    }
17756
17757    /**
17758     * <p>Return the time at which the drawing of the view hierarchy started.</p>
17759     *
17760     * @return the drawing start time in milliseconds
17761     */
17762    public long getDrawingTime() {
17763        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17764    }
17765
17766    /**
17767     * <p>Enables or disables the duplication of the parent's state into this view. When
17768     * duplication is enabled, this view gets its drawable state from its parent rather
17769     * than from its own internal properties.</p>
17770     *
17771     * <p>Note: in the current implementation, setting this property to true after the
17772     * view was added to a ViewGroup might have no effect at all. This property should
17773     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17774     *
17775     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17776     * property is enabled, an exception will be thrown.</p>
17777     *
17778     * <p>Note: if the child view uses and updates additional states which are unknown to the
17779     * parent, these states should not be affected by this method.</p>
17780     *
17781     * @param enabled True to enable duplication of the parent's drawable state, false
17782     *                to disable it.
17783     *
17784     * @see #getDrawableState()
17785     * @see #isDuplicateParentStateEnabled()
17786     */
17787    public void setDuplicateParentStateEnabled(boolean enabled) {
17788        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17789    }
17790
17791    /**
17792     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17793     *
17794     * @return True if this view's drawable state is duplicated from the parent,
17795     *         false otherwise
17796     *
17797     * @see #getDrawableState()
17798     * @see #setDuplicateParentStateEnabled(boolean)
17799     */
17800    public boolean isDuplicateParentStateEnabled() {
17801        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17802    }
17803
17804    /**
17805     * <p>Specifies the type of layer backing this view. The layer can be
17806     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17807     * {@link #LAYER_TYPE_HARDWARE}.</p>
17808     *
17809     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17810     * instance that controls how the layer is composed on screen. The following
17811     * properties of the paint are taken into account when composing the layer:</p>
17812     * <ul>
17813     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17814     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17815     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17816     * </ul>
17817     *
17818     * <p>If this view has an alpha value set to < 1.0 by calling
17819     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17820     * by this view's alpha value.</p>
17821     *
17822     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17823     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17824     * for more information on when and how to use layers.</p>
17825     *
17826     * @param layerType The type of layer to use with this view, must be one of
17827     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17828     *        {@link #LAYER_TYPE_HARDWARE}
17829     * @param paint The paint used to compose the layer. This argument is optional
17830     *        and can be null. It is ignored when the layer type is
17831     *        {@link #LAYER_TYPE_NONE}
17832     *
17833     * @see #getLayerType()
17834     * @see #LAYER_TYPE_NONE
17835     * @see #LAYER_TYPE_SOFTWARE
17836     * @see #LAYER_TYPE_HARDWARE
17837     * @see #setAlpha(float)
17838     *
17839     * @attr ref android.R.styleable#View_layerType
17840     */
17841    public void setLayerType(int layerType, @Nullable Paint paint) {
17842        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17843            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17844                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17845        }
17846
17847        boolean typeChanged = mRenderNode.setLayerType(layerType);
17848
17849        if (!typeChanged) {
17850            setLayerPaint(paint);
17851            return;
17852        }
17853
17854        if (layerType != LAYER_TYPE_SOFTWARE) {
17855            // Destroy any previous software drawing cache if present
17856            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17857            // drawing cache created in View#draw when drawing to a SW canvas.
17858            destroyDrawingCache();
17859        }
17860
17861        mLayerType = layerType;
17862        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17863        mRenderNode.setLayerPaint(mLayerPaint);
17864
17865        // draw() behaves differently if we are on a layer, so we need to
17866        // invalidate() here
17867        invalidateParentCaches();
17868        invalidate(true);
17869    }
17870
17871    /**
17872     * Updates the {@link Paint} object used with the current layer (used only if the current
17873     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17874     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17875     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17876     * ensure that the view gets redrawn immediately.
17877     *
17878     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17879     * instance that controls how the layer is composed on screen. The following
17880     * properties of the paint are taken into account when composing the layer:</p>
17881     * <ul>
17882     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17883     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17884     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17885     * </ul>
17886     *
17887     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17888     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17889     *
17890     * @param paint The paint used to compose the layer. This argument is optional
17891     *        and can be null. It is ignored when the layer type is
17892     *        {@link #LAYER_TYPE_NONE}
17893     *
17894     * @see #setLayerType(int, android.graphics.Paint)
17895     */
17896    public void setLayerPaint(@Nullable Paint paint) {
17897        int layerType = getLayerType();
17898        if (layerType != LAYER_TYPE_NONE) {
17899            mLayerPaint = paint;
17900            if (layerType == LAYER_TYPE_HARDWARE) {
17901                if (mRenderNode.setLayerPaint(paint)) {
17902                    invalidateViewProperty(false, false);
17903                }
17904            } else {
17905                invalidate();
17906            }
17907        }
17908    }
17909
17910    /**
17911     * Indicates what type of layer is currently associated with this view. By default
17912     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17913     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17914     * for more information on the different types of layers.
17915     *
17916     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17917     *         {@link #LAYER_TYPE_HARDWARE}
17918     *
17919     * @see #setLayerType(int, android.graphics.Paint)
17920     * @see #buildLayer()
17921     * @see #LAYER_TYPE_NONE
17922     * @see #LAYER_TYPE_SOFTWARE
17923     * @see #LAYER_TYPE_HARDWARE
17924     */
17925    public int getLayerType() {
17926        return mLayerType;
17927    }
17928
17929    /**
17930     * Forces this view's layer to be created and this view to be rendered
17931     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17932     * invoking this method will have no effect.
17933     *
17934     * This method can for instance be used to render a view into its layer before
17935     * starting an animation. If this view is complex, rendering into the layer
17936     * before starting the animation will avoid skipping frames.
17937     *
17938     * @throws IllegalStateException If this view is not attached to a window
17939     *
17940     * @see #setLayerType(int, android.graphics.Paint)
17941     */
17942    public void buildLayer() {
17943        if (mLayerType == LAYER_TYPE_NONE) return;
17944
17945        final AttachInfo attachInfo = mAttachInfo;
17946        if (attachInfo == null) {
17947            throw new IllegalStateException("This view must be attached to a window first");
17948        }
17949
17950        if (getWidth() == 0 || getHeight() == 0) {
17951            return;
17952        }
17953
17954        switch (mLayerType) {
17955            case LAYER_TYPE_HARDWARE:
17956                updateDisplayListIfDirty();
17957                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17958                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17959                }
17960                break;
17961            case LAYER_TYPE_SOFTWARE:
17962                buildDrawingCache(true);
17963                break;
17964        }
17965    }
17966
17967    /**
17968     * Destroys all hardware rendering resources. This method is invoked
17969     * when the system needs to reclaim resources. Upon execution of this
17970     * method, you should free any OpenGL resources created by the view.
17971     *
17972     * Note: you <strong>must</strong> call
17973     * <code>super.destroyHardwareResources()</code> when overriding
17974     * this method.
17975     *
17976     * @hide
17977     */
17978    @CallSuper
17979    protected void destroyHardwareResources() {
17980        if (mOverlay != null) {
17981            mOverlay.getOverlayView().destroyHardwareResources();
17982        }
17983        if (mGhostView != null) {
17984            mGhostView.destroyHardwareResources();
17985        }
17986    }
17987
17988    /**
17989     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17990     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17991     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17992     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17993     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17994     * null.</p>
17995     *
17996     * <p>Enabling the drawing cache is similar to
17997     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17998     * acceleration is turned off. When hardware acceleration is turned on, enabling the
17999     * drawing cache has no effect on rendering because the system uses a different mechanism
18000     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
18001     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
18002     * for information on how to enable software and hardware layers.</p>
18003     *
18004     * <p>This API can be used to manually generate
18005     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
18006     * {@link #getDrawingCache()}.</p>
18007     *
18008     * @param enabled true to enable the drawing cache, false otherwise
18009     *
18010     * @see #isDrawingCacheEnabled()
18011     * @see #getDrawingCache()
18012     * @see #buildDrawingCache()
18013     * @see #setLayerType(int, android.graphics.Paint)
18014     */
18015    public void setDrawingCacheEnabled(boolean enabled) {
18016        mCachingFailed = false;
18017        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
18018    }
18019
18020    /**
18021     * <p>Indicates whether the drawing cache is enabled for this view.</p>
18022     *
18023     * @return true if the drawing cache is enabled
18024     *
18025     * @see #setDrawingCacheEnabled(boolean)
18026     * @see #getDrawingCache()
18027     */
18028    @ViewDebug.ExportedProperty(category = "drawing")
18029    public boolean isDrawingCacheEnabled() {
18030        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
18031    }
18032
18033    /**
18034     * Debugging utility which recursively outputs the dirty state of a view and its
18035     * descendants.
18036     *
18037     * @hide
18038     */
18039    @SuppressWarnings({"UnusedDeclaration"})
18040    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
18041        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
18042                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
18043                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
18044                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
18045        if (clear) {
18046            mPrivateFlags &= clearMask;
18047        }
18048        if (this instanceof ViewGroup) {
18049            ViewGroup parent = (ViewGroup) this;
18050            final int count = parent.getChildCount();
18051            for (int i = 0; i < count; i++) {
18052                final View child = parent.getChildAt(i);
18053                child.outputDirtyFlags(indent + "  ", clear, clearMask);
18054            }
18055        }
18056    }
18057
18058    /**
18059     * This method is used by ViewGroup to cause its children to restore or recreate their
18060     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
18061     * to recreate its own display list, which would happen if it went through the normal
18062     * draw/dispatchDraw mechanisms.
18063     *
18064     * @hide
18065     */
18066    protected void dispatchGetDisplayList() {}
18067
18068    /**
18069     * A view that is not attached or hardware accelerated cannot create a display list.
18070     * This method checks these conditions and returns the appropriate result.
18071     *
18072     * @return true if view has the ability to create a display list, false otherwise.
18073     *
18074     * @hide
18075     */
18076    public boolean canHaveDisplayList() {
18077        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
18078    }
18079
18080    /**
18081     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
18082     * @hide
18083     */
18084    @NonNull
18085    public RenderNode updateDisplayListIfDirty() {
18086        final RenderNode renderNode = mRenderNode;
18087        if (!canHaveDisplayList()) {
18088            // can't populate RenderNode, don't try
18089            return renderNode;
18090        }
18091
18092        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
18093                || !renderNode.isValid()
18094                || (mRecreateDisplayList)) {
18095            // Don't need to recreate the display list, just need to tell our
18096            // children to restore/recreate theirs
18097            if (renderNode.isValid()
18098                    && !mRecreateDisplayList) {
18099                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18100                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18101                dispatchGetDisplayList();
18102
18103                return renderNode; // no work needed
18104            }
18105
18106            // If we got here, we're recreating it. Mark it as such to ensure that
18107            // we copy in child display lists into ours in drawChild()
18108            mRecreateDisplayList = true;
18109
18110            int width = mRight - mLeft;
18111            int height = mBottom - mTop;
18112            int layerType = getLayerType();
18113
18114            final DisplayListCanvas canvas = renderNode.start(width, height);
18115            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
18116
18117            try {
18118                if (layerType == LAYER_TYPE_SOFTWARE) {
18119                    buildDrawingCache(true);
18120                    Bitmap cache = getDrawingCache(true);
18121                    if (cache != null) {
18122                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
18123                    }
18124                } else {
18125                    computeScroll();
18126
18127                    canvas.translate(-mScrollX, -mScrollY);
18128                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18129                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18130
18131                    // Fast path for layouts with no backgrounds
18132                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18133                        dispatchDraw(canvas);
18134                        drawAutofilledHighlight(canvas);
18135                        if (mOverlay != null && !mOverlay.isEmpty()) {
18136                            mOverlay.getOverlayView().draw(canvas);
18137                        }
18138                        if (debugDraw()) {
18139                            debugDrawFocus(canvas);
18140                        }
18141                    } else {
18142                        draw(canvas);
18143                    }
18144                }
18145            } finally {
18146                renderNode.end(canvas);
18147                setDisplayListProperties(renderNode);
18148            }
18149        } else {
18150            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18151            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18152        }
18153        return renderNode;
18154    }
18155
18156    private void resetDisplayList() {
18157        mRenderNode.discardDisplayList();
18158        if (mBackgroundRenderNode != null) {
18159            mBackgroundRenderNode.discardDisplayList();
18160        }
18161    }
18162
18163    /**
18164     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
18165     *
18166     * @return A non-scaled bitmap representing this view or null if cache is disabled.
18167     *
18168     * @see #getDrawingCache(boolean)
18169     */
18170    public Bitmap getDrawingCache() {
18171        return getDrawingCache(false);
18172    }
18173
18174    /**
18175     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
18176     * is null when caching is disabled. If caching is enabled and the cache is not ready,
18177     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
18178     * draw from the cache when the cache is enabled. To benefit from the cache, you must
18179     * request the drawing cache by calling this method and draw it on screen if the
18180     * returned bitmap is not null.</p>
18181     *
18182     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
18183     * this method will create a bitmap of the same size as this view. Because this bitmap
18184     * will be drawn scaled by the parent ViewGroup, the result on screen might show
18185     * scaling artifacts. To avoid such artifacts, you should call this method by setting
18186     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
18187     * size than the view. This implies that your application must be able to handle this
18188     * size.</p>
18189     *
18190     * @param autoScale Indicates whether the generated bitmap should be scaled based on
18191     *        the current density of the screen when the application is in compatibility
18192     *        mode.
18193     *
18194     * @return A bitmap representing this view or null if cache is disabled.
18195     *
18196     * @see #setDrawingCacheEnabled(boolean)
18197     * @see #isDrawingCacheEnabled()
18198     * @see #buildDrawingCache(boolean)
18199     * @see #destroyDrawingCache()
18200     */
18201    public Bitmap getDrawingCache(boolean autoScale) {
18202        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
18203            return null;
18204        }
18205        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
18206            buildDrawingCache(autoScale);
18207        }
18208        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
18209    }
18210
18211    /**
18212     * <p>Frees the resources used by the drawing cache. If you call
18213     * {@link #buildDrawingCache()} manually without calling
18214     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
18215     * should cleanup the cache with this method afterwards.</p>
18216     *
18217     * @see #setDrawingCacheEnabled(boolean)
18218     * @see #buildDrawingCache()
18219     * @see #getDrawingCache()
18220     */
18221    public void destroyDrawingCache() {
18222        if (mDrawingCache != null) {
18223            mDrawingCache.recycle();
18224            mDrawingCache = null;
18225        }
18226        if (mUnscaledDrawingCache != null) {
18227            mUnscaledDrawingCache.recycle();
18228            mUnscaledDrawingCache = null;
18229        }
18230    }
18231
18232    /**
18233     * Setting a solid background color for the drawing cache's bitmaps will improve
18234     * performance and memory usage. Note, though that this should only be used if this
18235     * view will always be drawn on top of a solid color.
18236     *
18237     * @param color The background color to use for the drawing cache's bitmap
18238     *
18239     * @see #setDrawingCacheEnabled(boolean)
18240     * @see #buildDrawingCache()
18241     * @see #getDrawingCache()
18242     */
18243    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
18244        if (color != mDrawingCacheBackgroundColor) {
18245            mDrawingCacheBackgroundColor = color;
18246            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18247        }
18248    }
18249
18250    /**
18251     * @see #setDrawingCacheBackgroundColor(int)
18252     *
18253     * @return The background color to used for the drawing cache's bitmap
18254     */
18255    @ColorInt
18256    public int getDrawingCacheBackgroundColor() {
18257        return mDrawingCacheBackgroundColor;
18258    }
18259
18260    /**
18261     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
18262     *
18263     * @see #buildDrawingCache(boolean)
18264     */
18265    public void buildDrawingCache() {
18266        buildDrawingCache(false);
18267    }
18268
18269    /**
18270     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
18271     *
18272     * <p>If you call {@link #buildDrawingCache()} manually without calling
18273     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
18274     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
18275     *
18276     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
18277     * this method will create a bitmap of the same size as this view. Because this bitmap
18278     * will be drawn scaled by the parent ViewGroup, the result on screen might show
18279     * scaling artifacts. To avoid such artifacts, you should call this method by setting
18280     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
18281     * size than the view. This implies that your application must be able to handle this
18282     * size.</p>
18283     *
18284     * <p>You should avoid calling this method when hardware acceleration is enabled. If
18285     * you do not need the drawing cache bitmap, calling this method will increase memory
18286     * usage and cause the view to be rendered in software once, thus negatively impacting
18287     * performance.</p>
18288     *
18289     * @see #getDrawingCache()
18290     * @see #destroyDrawingCache()
18291     */
18292    public void buildDrawingCache(boolean autoScale) {
18293        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
18294                mDrawingCache == null : mUnscaledDrawingCache == null)) {
18295            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
18296                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
18297                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
18298            }
18299            try {
18300                buildDrawingCacheImpl(autoScale);
18301            } finally {
18302                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
18303            }
18304        }
18305    }
18306
18307    /**
18308     * private, internal implementation of buildDrawingCache, used to enable tracing
18309     */
18310    private void buildDrawingCacheImpl(boolean autoScale) {
18311        mCachingFailed = false;
18312
18313        int width = mRight - mLeft;
18314        int height = mBottom - mTop;
18315
18316        final AttachInfo attachInfo = mAttachInfo;
18317        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
18318
18319        if (autoScale && scalingRequired) {
18320            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
18321            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
18322        }
18323
18324        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
18325        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
18326        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
18327
18328        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
18329        final long drawingCacheSize =
18330                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
18331        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
18332            if (width > 0 && height > 0) {
18333                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
18334                        + " too large to fit into a software layer (or drawing cache), needs "
18335                        + projectedBitmapSize + " bytes, only "
18336                        + drawingCacheSize + " available");
18337            }
18338            destroyDrawingCache();
18339            mCachingFailed = true;
18340            return;
18341        }
18342
18343        boolean clear = true;
18344        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
18345
18346        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
18347            Bitmap.Config quality;
18348            if (!opaque) {
18349                // Never pick ARGB_4444 because it looks awful
18350                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
18351                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
18352                    case DRAWING_CACHE_QUALITY_AUTO:
18353                    case DRAWING_CACHE_QUALITY_LOW:
18354                    case DRAWING_CACHE_QUALITY_HIGH:
18355                    default:
18356                        quality = Bitmap.Config.ARGB_8888;
18357                        break;
18358                }
18359            } else {
18360                // Optimization for translucent windows
18361                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
18362                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
18363            }
18364
18365            // Try to cleanup memory
18366            if (bitmap != null) bitmap.recycle();
18367
18368            try {
18369                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18370                        width, height, quality);
18371                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
18372                if (autoScale) {
18373                    mDrawingCache = bitmap;
18374                } else {
18375                    mUnscaledDrawingCache = bitmap;
18376                }
18377                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
18378            } catch (OutOfMemoryError e) {
18379                // If there is not enough memory to create the bitmap cache, just
18380                // ignore the issue as bitmap caches are not required to draw the
18381                // view hierarchy
18382                if (autoScale) {
18383                    mDrawingCache = null;
18384                } else {
18385                    mUnscaledDrawingCache = null;
18386                }
18387                mCachingFailed = true;
18388                return;
18389            }
18390
18391            clear = drawingCacheBackgroundColor != 0;
18392        }
18393
18394        Canvas canvas;
18395        if (attachInfo != null) {
18396            canvas = attachInfo.mCanvas;
18397            if (canvas == null) {
18398                canvas = new Canvas();
18399            }
18400            canvas.setBitmap(bitmap);
18401            // Temporarily clobber the cached Canvas in case one of our children
18402            // is also using a drawing cache. Without this, the children would
18403            // steal the canvas by attaching their own bitmap to it and bad, bad
18404            // thing would happen (invisible views, corrupted drawings, etc.)
18405            attachInfo.mCanvas = null;
18406        } else {
18407            // This case should hopefully never or seldom happen
18408            canvas = new Canvas(bitmap);
18409        }
18410
18411        if (clear) {
18412            bitmap.eraseColor(drawingCacheBackgroundColor);
18413        }
18414
18415        computeScroll();
18416        final int restoreCount = canvas.save();
18417
18418        if (autoScale && scalingRequired) {
18419            final float scale = attachInfo.mApplicationScale;
18420            canvas.scale(scale, scale);
18421        }
18422
18423        canvas.translate(-mScrollX, -mScrollY);
18424
18425        mPrivateFlags |= PFLAG_DRAWN;
18426        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
18427                mLayerType != LAYER_TYPE_NONE) {
18428            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
18429        }
18430
18431        // Fast path for layouts with no backgrounds
18432        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18433            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18434            dispatchDraw(canvas);
18435            drawAutofilledHighlight(canvas);
18436            if (mOverlay != null && !mOverlay.isEmpty()) {
18437                mOverlay.getOverlayView().draw(canvas);
18438            }
18439        } else {
18440            draw(canvas);
18441        }
18442
18443        canvas.restoreToCount(restoreCount);
18444        canvas.setBitmap(null);
18445
18446        if (attachInfo != null) {
18447            // Restore the cached Canvas for our siblings
18448            attachInfo.mCanvas = canvas;
18449        }
18450    }
18451
18452    /**
18453     * Create a snapshot of the view into a bitmap.  We should probably make
18454     * some form of this public, but should think about the API.
18455     *
18456     * @hide
18457     */
18458    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
18459        int width = mRight - mLeft;
18460        int height = mBottom - mTop;
18461
18462        final AttachInfo attachInfo = mAttachInfo;
18463        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
18464        width = (int) ((width * scale) + 0.5f);
18465        height = (int) ((height * scale) + 0.5f);
18466
18467        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18468                width > 0 ? width : 1, height > 0 ? height : 1, quality);
18469        if (bitmap == null) {
18470            throw new OutOfMemoryError();
18471        }
18472
18473        Resources resources = getResources();
18474        if (resources != null) {
18475            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
18476        }
18477
18478        Canvas canvas;
18479        if (attachInfo != null) {
18480            canvas = attachInfo.mCanvas;
18481            if (canvas == null) {
18482                canvas = new Canvas();
18483            }
18484            canvas.setBitmap(bitmap);
18485            // Temporarily clobber the cached Canvas in case one of our children
18486            // is also using a drawing cache. Without this, the children would
18487            // steal the canvas by attaching their own bitmap to it and bad, bad
18488            // things would happen (invisible views, corrupted drawings, etc.)
18489            attachInfo.mCanvas = null;
18490        } else {
18491            // This case should hopefully never or seldom happen
18492            canvas = new Canvas(bitmap);
18493        }
18494        boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
18495        canvas.setHwBitmapsInSwModeEnabled(true);
18496        if ((backgroundColor & 0xff000000) != 0) {
18497            bitmap.eraseColor(backgroundColor);
18498        }
18499
18500        computeScroll();
18501        final int restoreCount = canvas.save();
18502        canvas.scale(scale, scale);
18503        canvas.translate(-mScrollX, -mScrollY);
18504
18505        // Temporarily remove the dirty mask
18506        int flags = mPrivateFlags;
18507        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18508
18509        // Fast path for layouts with no backgrounds
18510        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18511            dispatchDraw(canvas);
18512            drawAutofilledHighlight(canvas);
18513            if (mOverlay != null && !mOverlay.isEmpty()) {
18514                mOverlay.getOverlayView().draw(canvas);
18515            }
18516        } else {
18517            draw(canvas);
18518        }
18519
18520        mPrivateFlags = flags;
18521
18522        canvas.restoreToCount(restoreCount);
18523        canvas.setBitmap(null);
18524        canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
18525
18526        if (attachInfo != null) {
18527            // Restore the cached Canvas for our siblings
18528            attachInfo.mCanvas = canvas;
18529        }
18530
18531        return bitmap;
18532    }
18533
18534    /**
18535     * Indicates whether this View is currently in edit mode. A View is usually
18536     * in edit mode when displayed within a developer tool. For instance, if
18537     * this View is being drawn by a visual user interface builder, this method
18538     * should return true.
18539     *
18540     * Subclasses should check the return value of this method to provide
18541     * different behaviors if their normal behavior might interfere with the
18542     * host environment. For instance: the class spawns a thread in its
18543     * constructor, the drawing code relies on device-specific features, etc.
18544     *
18545     * This method is usually checked in the drawing code of custom widgets.
18546     *
18547     * @return True if this View is in edit mode, false otherwise.
18548     */
18549    public boolean isInEditMode() {
18550        return false;
18551    }
18552
18553    /**
18554     * If the View draws content inside its padding and enables fading edges,
18555     * it needs to support padding offsets. Padding offsets are added to the
18556     * fading edges to extend the length of the fade so that it covers pixels
18557     * drawn inside the padding.
18558     *
18559     * Subclasses of this class should override this method if they need
18560     * to draw content inside the padding.
18561     *
18562     * @return True if padding offset must be applied, false otherwise.
18563     *
18564     * @see #getLeftPaddingOffset()
18565     * @see #getRightPaddingOffset()
18566     * @see #getTopPaddingOffset()
18567     * @see #getBottomPaddingOffset()
18568     *
18569     * @since CURRENT
18570     */
18571    protected boolean isPaddingOffsetRequired() {
18572        return false;
18573    }
18574
18575    /**
18576     * Amount by which to extend the left fading region. Called only when
18577     * {@link #isPaddingOffsetRequired()} returns true.
18578     *
18579     * @return The left padding offset in pixels.
18580     *
18581     * @see #isPaddingOffsetRequired()
18582     *
18583     * @since CURRENT
18584     */
18585    protected int getLeftPaddingOffset() {
18586        return 0;
18587    }
18588
18589    /**
18590     * Amount by which to extend the right fading region. Called only when
18591     * {@link #isPaddingOffsetRequired()} returns true.
18592     *
18593     * @return The right padding offset in pixels.
18594     *
18595     * @see #isPaddingOffsetRequired()
18596     *
18597     * @since CURRENT
18598     */
18599    protected int getRightPaddingOffset() {
18600        return 0;
18601    }
18602
18603    /**
18604     * Amount by which to extend the top fading region. Called only when
18605     * {@link #isPaddingOffsetRequired()} returns true.
18606     *
18607     * @return The top padding offset in pixels.
18608     *
18609     * @see #isPaddingOffsetRequired()
18610     *
18611     * @since CURRENT
18612     */
18613    protected int getTopPaddingOffset() {
18614        return 0;
18615    }
18616
18617    /**
18618     * Amount by which to extend the bottom fading region. Called only when
18619     * {@link #isPaddingOffsetRequired()} returns true.
18620     *
18621     * @return The bottom padding offset in pixels.
18622     *
18623     * @see #isPaddingOffsetRequired()
18624     *
18625     * @since CURRENT
18626     */
18627    protected int getBottomPaddingOffset() {
18628        return 0;
18629    }
18630
18631    /**
18632     * @hide
18633     * @param offsetRequired
18634     */
18635    protected int getFadeTop(boolean offsetRequired) {
18636        int top = mPaddingTop;
18637        if (offsetRequired) top += getTopPaddingOffset();
18638        return top;
18639    }
18640
18641    /**
18642     * @hide
18643     * @param offsetRequired
18644     */
18645    protected int getFadeHeight(boolean offsetRequired) {
18646        int padding = mPaddingTop;
18647        if (offsetRequired) padding += getTopPaddingOffset();
18648        return mBottom - mTop - mPaddingBottom - padding;
18649    }
18650
18651    /**
18652     * <p>Indicates whether this view is attached to a hardware accelerated
18653     * window or not.</p>
18654     *
18655     * <p>Even if this method returns true, it does not mean that every call
18656     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18657     * accelerated {@link android.graphics.Canvas}. For instance, if this view
18658     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18659     * window is hardware accelerated,
18660     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18661     * return false, and this method will return true.</p>
18662     *
18663     * @return True if the view is attached to a window and the window is
18664     *         hardware accelerated; false in any other case.
18665     */
18666    @ViewDebug.ExportedProperty(category = "drawing")
18667    public boolean isHardwareAccelerated() {
18668        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18669    }
18670
18671    /**
18672     * Sets a rectangular area on this view to which the view will be clipped
18673     * when it is drawn. Setting the value to null will remove the clip bounds
18674     * and the view will draw normally, using its full bounds.
18675     *
18676     * @param clipBounds The rectangular area, in the local coordinates of
18677     * this view, to which future drawing operations will be clipped.
18678     */
18679    public void setClipBounds(Rect clipBounds) {
18680        if (clipBounds == mClipBounds
18681                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18682            return;
18683        }
18684        if (clipBounds != null) {
18685            if (mClipBounds == null) {
18686                mClipBounds = new Rect(clipBounds);
18687            } else {
18688                mClipBounds.set(clipBounds);
18689            }
18690        } else {
18691            mClipBounds = null;
18692        }
18693        mRenderNode.setClipBounds(mClipBounds);
18694        invalidateViewProperty(false, false);
18695    }
18696
18697    /**
18698     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18699     *
18700     * @return A copy of the current clip bounds if clip bounds are set,
18701     * otherwise null.
18702     */
18703    public Rect getClipBounds() {
18704        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18705    }
18706
18707
18708    /**
18709     * Populates an output rectangle with the clip bounds of the view,
18710     * returning {@code true} if successful or {@code false} if the view's
18711     * clip bounds are {@code null}.
18712     *
18713     * @param outRect rectangle in which to place the clip bounds of the view
18714     * @return {@code true} if successful or {@code false} if the view's
18715     *         clip bounds are {@code null}
18716     */
18717    public boolean getClipBounds(Rect outRect) {
18718        if (mClipBounds != null) {
18719            outRect.set(mClipBounds);
18720            return true;
18721        }
18722        return false;
18723    }
18724
18725    /**
18726     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18727     * case of an active Animation being run on the view.
18728     */
18729    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18730            Animation a, boolean scalingRequired) {
18731        Transformation invalidationTransform;
18732        final int flags = parent.mGroupFlags;
18733        final boolean initialized = a.isInitialized();
18734        if (!initialized) {
18735            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18736            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18737            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18738            onAnimationStart();
18739        }
18740
18741        final Transformation t = parent.getChildTransformation();
18742        boolean more = a.getTransformation(drawingTime, t, 1f);
18743        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18744            if (parent.mInvalidationTransformation == null) {
18745                parent.mInvalidationTransformation = new Transformation();
18746            }
18747            invalidationTransform = parent.mInvalidationTransformation;
18748            a.getTransformation(drawingTime, invalidationTransform, 1f);
18749        } else {
18750            invalidationTransform = t;
18751        }
18752
18753        if (more) {
18754            if (!a.willChangeBounds()) {
18755                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18756                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18757                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18758                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18759                    // The child need to draw an animation, potentially offscreen, so
18760                    // make sure we do not cancel invalidate requests
18761                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18762                    parent.invalidate(mLeft, mTop, mRight, mBottom);
18763                }
18764            } else {
18765                if (parent.mInvalidateRegion == null) {
18766                    parent.mInvalidateRegion = new RectF();
18767                }
18768                final RectF region = parent.mInvalidateRegion;
18769                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18770                        invalidationTransform);
18771
18772                // The child need to draw an animation, potentially offscreen, so
18773                // make sure we do not cancel invalidate requests
18774                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18775
18776                final int left = mLeft + (int) region.left;
18777                final int top = mTop + (int) region.top;
18778                parent.invalidate(left, top, left + (int) (region.width() + .5f),
18779                        top + (int) (region.height() + .5f));
18780            }
18781        }
18782        return more;
18783    }
18784
18785    /**
18786     * This method is called by getDisplayList() when a display list is recorded for a View.
18787     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18788     */
18789    void setDisplayListProperties(RenderNode renderNode) {
18790        if (renderNode != null) {
18791            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18792            renderNode.setClipToBounds(mParent instanceof ViewGroup
18793                    && ((ViewGroup) mParent).getClipChildren());
18794
18795            float alpha = 1;
18796            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18797                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18798                ViewGroup parentVG = (ViewGroup) mParent;
18799                final Transformation t = parentVG.getChildTransformation();
18800                if (parentVG.getChildStaticTransformation(this, t)) {
18801                    final int transformType = t.getTransformationType();
18802                    if (transformType != Transformation.TYPE_IDENTITY) {
18803                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18804                            alpha = t.getAlpha();
18805                        }
18806                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18807                            renderNode.setStaticMatrix(t.getMatrix());
18808                        }
18809                    }
18810                }
18811            }
18812            if (mTransformationInfo != null) {
18813                alpha *= getFinalAlpha();
18814                if (alpha < 1) {
18815                    final int multipliedAlpha = (int) (255 * alpha);
18816                    if (onSetAlpha(multipliedAlpha)) {
18817                        alpha = 1;
18818                    }
18819                }
18820                renderNode.setAlpha(alpha);
18821            } else if (alpha < 1) {
18822                renderNode.setAlpha(alpha);
18823            }
18824        }
18825    }
18826
18827    /**
18828     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18829     *
18830     * This is where the View specializes rendering behavior based on layer type,
18831     * and hardware acceleration.
18832     */
18833    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18834        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18835        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18836         *
18837         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18838         * HW accelerated, it can't handle drawing RenderNodes.
18839         */
18840        boolean drawingWithRenderNode = mAttachInfo != null
18841                && mAttachInfo.mHardwareAccelerated
18842                && hardwareAcceleratedCanvas;
18843
18844        boolean more = false;
18845        final boolean childHasIdentityMatrix = hasIdentityMatrix();
18846        final int parentFlags = parent.mGroupFlags;
18847
18848        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18849            parent.getChildTransformation().clear();
18850            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18851        }
18852
18853        Transformation transformToApply = null;
18854        boolean concatMatrix = false;
18855        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18856        final Animation a = getAnimation();
18857        if (a != null) {
18858            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18859            concatMatrix = a.willChangeTransformationMatrix();
18860            if (concatMatrix) {
18861                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18862            }
18863            transformToApply = parent.getChildTransformation();
18864        } else {
18865            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18866                // No longer animating: clear out old animation matrix
18867                mRenderNode.setAnimationMatrix(null);
18868                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18869            }
18870            if (!drawingWithRenderNode
18871                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18872                final Transformation t = parent.getChildTransformation();
18873                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18874                if (hasTransform) {
18875                    final int transformType = t.getTransformationType();
18876                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18877                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18878                }
18879            }
18880        }
18881
18882        concatMatrix |= !childHasIdentityMatrix;
18883
18884        // Sets the flag as early as possible to allow draw() implementations
18885        // to call invalidate() successfully when doing animations
18886        mPrivateFlags |= PFLAG_DRAWN;
18887
18888        if (!concatMatrix &&
18889                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18890                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18891                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18892                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18893            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18894            return more;
18895        }
18896        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18897
18898        if (hardwareAcceleratedCanvas) {
18899            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18900            // retain the flag's value temporarily in the mRecreateDisplayList flag
18901            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18902            mPrivateFlags &= ~PFLAG_INVALIDATED;
18903        }
18904
18905        RenderNode renderNode = null;
18906        Bitmap cache = null;
18907        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18908        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18909             if (layerType != LAYER_TYPE_NONE) {
18910                 // If not drawing with RenderNode, treat HW layers as SW
18911                 layerType = LAYER_TYPE_SOFTWARE;
18912                 buildDrawingCache(true);
18913            }
18914            cache = getDrawingCache(true);
18915        }
18916
18917        if (drawingWithRenderNode) {
18918            // Delay getting the display list until animation-driven alpha values are
18919            // set up and possibly passed on to the view
18920            renderNode = updateDisplayListIfDirty();
18921            if (!renderNode.isValid()) {
18922                // Uncommon, but possible. If a view is removed from the hierarchy during the call
18923                // to getDisplayList(), the display list will be marked invalid and we should not
18924                // try to use it again.
18925                renderNode = null;
18926                drawingWithRenderNode = false;
18927            }
18928        }
18929
18930        int sx = 0;
18931        int sy = 0;
18932        if (!drawingWithRenderNode) {
18933            computeScroll();
18934            sx = mScrollX;
18935            sy = mScrollY;
18936        }
18937
18938        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18939        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18940
18941        int restoreTo = -1;
18942        if (!drawingWithRenderNode || transformToApply != null) {
18943            restoreTo = canvas.save();
18944        }
18945        if (offsetForScroll) {
18946            canvas.translate(mLeft - sx, mTop - sy);
18947        } else {
18948            if (!drawingWithRenderNode) {
18949                canvas.translate(mLeft, mTop);
18950            }
18951            if (scalingRequired) {
18952                if (drawingWithRenderNode) {
18953                    // TODO: Might not need this if we put everything inside the DL
18954                    restoreTo = canvas.save();
18955                }
18956                // mAttachInfo cannot be null, otherwise scalingRequired == false
18957                final float scale = 1.0f / mAttachInfo.mApplicationScale;
18958                canvas.scale(scale, scale);
18959            }
18960        }
18961
18962        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18963        if (transformToApply != null
18964                || alpha < 1
18965                || !hasIdentityMatrix()
18966                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18967            if (transformToApply != null || !childHasIdentityMatrix) {
18968                int transX = 0;
18969                int transY = 0;
18970
18971                if (offsetForScroll) {
18972                    transX = -sx;
18973                    transY = -sy;
18974                }
18975
18976                if (transformToApply != null) {
18977                    if (concatMatrix) {
18978                        if (drawingWithRenderNode) {
18979                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
18980                        } else {
18981                            // Undo the scroll translation, apply the transformation matrix,
18982                            // then redo the scroll translate to get the correct result.
18983                            canvas.translate(-transX, -transY);
18984                            canvas.concat(transformToApply.getMatrix());
18985                            canvas.translate(transX, transY);
18986                        }
18987                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18988                    }
18989
18990                    float transformAlpha = transformToApply.getAlpha();
18991                    if (transformAlpha < 1) {
18992                        alpha *= transformAlpha;
18993                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18994                    }
18995                }
18996
18997                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18998                    canvas.translate(-transX, -transY);
18999                    canvas.concat(getMatrix());
19000                    canvas.translate(transX, transY);
19001                }
19002            }
19003
19004            // Deal with alpha if it is or used to be <1
19005            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
19006                if (alpha < 1) {
19007                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
19008                } else {
19009                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
19010                }
19011                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
19012                if (!drawingWithDrawingCache) {
19013                    final int multipliedAlpha = (int) (255 * alpha);
19014                    if (!onSetAlpha(multipliedAlpha)) {
19015                        if (drawingWithRenderNode) {
19016                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
19017                        } else if (layerType == LAYER_TYPE_NONE) {
19018                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
19019                                    multipliedAlpha);
19020                        }
19021                    } else {
19022                        // Alpha is handled by the child directly, clobber the layer's alpha
19023                        mPrivateFlags |= PFLAG_ALPHA_SET;
19024                    }
19025                }
19026            }
19027        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
19028            onSetAlpha(255);
19029            mPrivateFlags &= ~PFLAG_ALPHA_SET;
19030        }
19031
19032        if (!drawingWithRenderNode) {
19033            // apply clips directly, since RenderNode won't do it for this draw
19034            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
19035                if (offsetForScroll) {
19036                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
19037                } else {
19038                    if (!scalingRequired || cache == null) {
19039                        canvas.clipRect(0, 0, getWidth(), getHeight());
19040                    } else {
19041                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
19042                    }
19043                }
19044            }
19045
19046            if (mClipBounds != null) {
19047                // clip bounds ignore scroll
19048                canvas.clipRect(mClipBounds);
19049            }
19050        }
19051
19052        if (!drawingWithDrawingCache) {
19053            if (drawingWithRenderNode) {
19054                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19055                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
19056            } else {
19057                // Fast path for layouts with no backgrounds
19058                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
19059                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19060                    dispatchDraw(canvas);
19061                } else {
19062                    draw(canvas);
19063                }
19064            }
19065        } else if (cache != null) {
19066            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
19067            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
19068                // no layer paint, use temporary paint to draw bitmap
19069                Paint cachePaint = parent.mCachePaint;
19070                if (cachePaint == null) {
19071                    cachePaint = new Paint();
19072                    cachePaint.setDither(false);
19073                    parent.mCachePaint = cachePaint;
19074                }
19075                cachePaint.setAlpha((int) (alpha * 255));
19076                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
19077            } else {
19078                // use layer paint to draw the bitmap, merging the two alphas, but also restore
19079                int layerPaintAlpha = mLayerPaint.getAlpha();
19080                if (alpha < 1) {
19081                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
19082                }
19083                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
19084                if (alpha < 1) {
19085                    mLayerPaint.setAlpha(layerPaintAlpha);
19086                }
19087            }
19088        }
19089
19090        if (restoreTo >= 0) {
19091            canvas.restoreToCount(restoreTo);
19092        }
19093
19094        if (a != null && !more) {
19095            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
19096                onSetAlpha(255);
19097            }
19098            parent.finishAnimatingView(this, a);
19099        }
19100
19101        if (more && hardwareAcceleratedCanvas) {
19102            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
19103                // alpha animations should cause the child to recreate its display list
19104                invalidate(true);
19105            }
19106        }
19107
19108        mRecreateDisplayList = false;
19109
19110        return more;
19111    }
19112
19113    static Paint getDebugPaint() {
19114        if (sDebugPaint == null) {
19115            sDebugPaint = new Paint();
19116            sDebugPaint.setAntiAlias(false);
19117        }
19118        return sDebugPaint;
19119    }
19120
19121    final int dipsToPixels(int dips) {
19122        float scale = getContext().getResources().getDisplayMetrics().density;
19123        return (int) (dips * scale + 0.5f);
19124    }
19125
19126    final private void debugDrawFocus(Canvas canvas) {
19127        if (isFocused()) {
19128            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
19129            final int l = mScrollX;
19130            final int r = l + mRight - mLeft;
19131            final int t = mScrollY;
19132            final int b = t + mBottom - mTop;
19133
19134            final Paint paint = getDebugPaint();
19135            paint.setColor(DEBUG_CORNERS_COLOR);
19136
19137            // Draw squares in corners.
19138            paint.setStyle(Paint.Style.FILL);
19139            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
19140            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
19141            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
19142            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
19143
19144            // Draw big X across the view.
19145            paint.setStyle(Paint.Style.STROKE);
19146            canvas.drawLine(l, t, r, b, paint);
19147            canvas.drawLine(l, b, r, t, paint);
19148        }
19149    }
19150
19151    /**
19152     * Manually render this view (and all of its children) to the given Canvas.
19153     * The view must have already done a full layout before this function is
19154     * called.  When implementing a view, implement
19155     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
19156     * If you do need to override this method, call the superclass version.
19157     *
19158     * @param canvas The Canvas to which the View is rendered.
19159     */
19160    @CallSuper
19161    public void draw(Canvas canvas) {
19162        final int privateFlags = mPrivateFlags;
19163        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
19164                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
19165        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
19166
19167        /*
19168         * Draw traversal performs several drawing steps which must be executed
19169         * in the appropriate order:
19170         *
19171         *      1. Draw the background
19172         *      2. If necessary, save the canvas' layers to prepare for fading
19173         *      3. Draw view's content
19174         *      4. Draw children
19175         *      5. If necessary, draw the fading edges and restore layers
19176         *      6. Draw decorations (scrollbars for instance)
19177         */
19178
19179        // Step 1, draw the background, if needed
19180        int saveCount;
19181
19182        if (!dirtyOpaque) {
19183            drawBackground(canvas);
19184        }
19185
19186        // skip step 2 & 5 if possible (common case)
19187        final int viewFlags = mViewFlags;
19188        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
19189        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
19190        if (!verticalEdges && !horizontalEdges) {
19191            // Step 3, draw the content
19192            if (!dirtyOpaque) onDraw(canvas);
19193
19194            // Step 4, draw the children
19195            dispatchDraw(canvas);
19196
19197            drawAutofilledHighlight(canvas);
19198
19199            // Overlay is part of the content and draws beneath Foreground
19200            if (mOverlay != null && !mOverlay.isEmpty()) {
19201                mOverlay.getOverlayView().dispatchDraw(canvas);
19202            }
19203
19204            // Step 6, draw decorations (foreground, scrollbars)
19205            onDrawForeground(canvas);
19206
19207            // Step 7, draw the default focus highlight
19208            drawDefaultFocusHighlight(canvas);
19209
19210            if (debugDraw()) {
19211                debugDrawFocus(canvas);
19212            }
19213
19214            // we're done...
19215            return;
19216        }
19217
19218        /*
19219         * Here we do the full fledged routine...
19220         * (this is an uncommon case where speed matters less,
19221         * this is why we repeat some of the tests that have been
19222         * done above)
19223         */
19224
19225        boolean drawTop = false;
19226        boolean drawBottom = false;
19227        boolean drawLeft = false;
19228        boolean drawRight = false;
19229
19230        float topFadeStrength = 0.0f;
19231        float bottomFadeStrength = 0.0f;
19232        float leftFadeStrength = 0.0f;
19233        float rightFadeStrength = 0.0f;
19234
19235        // Step 2, save the canvas' layers
19236        int paddingLeft = mPaddingLeft;
19237
19238        final boolean offsetRequired = isPaddingOffsetRequired();
19239        if (offsetRequired) {
19240            paddingLeft += getLeftPaddingOffset();
19241        }
19242
19243        int left = mScrollX + paddingLeft;
19244        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
19245        int top = mScrollY + getFadeTop(offsetRequired);
19246        int bottom = top + getFadeHeight(offsetRequired);
19247
19248        if (offsetRequired) {
19249            right += getRightPaddingOffset();
19250            bottom += getBottomPaddingOffset();
19251        }
19252
19253        final ScrollabilityCache scrollabilityCache = mScrollCache;
19254        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
19255        int length = (int) fadeHeight;
19256
19257        // clip the fade length if top and bottom fades overlap
19258        // overlapping fades produce odd-looking artifacts
19259        if (verticalEdges && (top + length > bottom - length)) {
19260            length = (bottom - top) / 2;
19261        }
19262
19263        // also clip horizontal fades if necessary
19264        if (horizontalEdges && (left + length > right - length)) {
19265            length = (right - left) / 2;
19266        }
19267
19268        if (verticalEdges) {
19269            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
19270            drawTop = topFadeStrength * fadeHeight > 1.0f;
19271            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
19272            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
19273        }
19274
19275        if (horizontalEdges) {
19276            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
19277            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
19278            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
19279            drawRight = rightFadeStrength * fadeHeight > 1.0f;
19280        }
19281
19282        saveCount = canvas.getSaveCount();
19283
19284        int solidColor = getSolidColor();
19285        if (solidColor == 0) {
19286            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
19287
19288            if (drawTop) {
19289                canvas.saveLayer(left, top, right, top + length, null, flags);
19290            }
19291
19292            if (drawBottom) {
19293                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
19294            }
19295
19296            if (drawLeft) {
19297                canvas.saveLayer(left, top, left + length, bottom, null, flags);
19298            }
19299
19300            if (drawRight) {
19301                canvas.saveLayer(right - length, top, right, bottom, null, flags);
19302            }
19303        } else {
19304            scrollabilityCache.setFadeColor(solidColor);
19305        }
19306
19307        // Step 3, draw the content
19308        if (!dirtyOpaque) onDraw(canvas);
19309
19310        // Step 4, draw the children
19311        dispatchDraw(canvas);
19312
19313        // Step 5, draw the fade effect and restore layers
19314        final Paint p = scrollabilityCache.paint;
19315        final Matrix matrix = scrollabilityCache.matrix;
19316        final Shader fade = scrollabilityCache.shader;
19317
19318        if (drawTop) {
19319            matrix.setScale(1, fadeHeight * topFadeStrength);
19320            matrix.postTranslate(left, top);
19321            fade.setLocalMatrix(matrix);
19322            p.setShader(fade);
19323            canvas.drawRect(left, top, right, top + length, p);
19324        }
19325
19326        if (drawBottom) {
19327            matrix.setScale(1, fadeHeight * bottomFadeStrength);
19328            matrix.postRotate(180);
19329            matrix.postTranslate(left, bottom);
19330            fade.setLocalMatrix(matrix);
19331            p.setShader(fade);
19332            canvas.drawRect(left, bottom - length, right, bottom, p);
19333        }
19334
19335        if (drawLeft) {
19336            matrix.setScale(1, fadeHeight * leftFadeStrength);
19337            matrix.postRotate(-90);
19338            matrix.postTranslate(left, top);
19339            fade.setLocalMatrix(matrix);
19340            p.setShader(fade);
19341            canvas.drawRect(left, top, left + length, bottom, p);
19342        }
19343
19344        if (drawRight) {
19345            matrix.setScale(1, fadeHeight * rightFadeStrength);
19346            matrix.postRotate(90);
19347            matrix.postTranslate(right, top);
19348            fade.setLocalMatrix(matrix);
19349            p.setShader(fade);
19350            canvas.drawRect(right - length, top, right, bottom, p);
19351        }
19352
19353        canvas.restoreToCount(saveCount);
19354
19355        drawAutofilledHighlight(canvas);
19356
19357        // Overlay is part of the content and draws beneath Foreground
19358        if (mOverlay != null && !mOverlay.isEmpty()) {
19359            mOverlay.getOverlayView().dispatchDraw(canvas);
19360        }
19361
19362        // Step 6, draw decorations (foreground, scrollbars)
19363        onDrawForeground(canvas);
19364
19365        if (debugDraw()) {
19366            debugDrawFocus(canvas);
19367        }
19368    }
19369
19370    /**
19371     * Draws the background onto the specified canvas.
19372     *
19373     * @param canvas Canvas on which to draw the background
19374     */
19375    private void drawBackground(Canvas canvas) {
19376        final Drawable background = mBackground;
19377        if (background == null) {
19378            return;
19379        }
19380
19381        setBackgroundBounds();
19382
19383        // Attempt to use a display list if requested.
19384        if (canvas.isHardwareAccelerated() && mAttachInfo != null
19385                && mAttachInfo.mThreadedRenderer != null) {
19386            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
19387
19388            final RenderNode renderNode = mBackgroundRenderNode;
19389            if (renderNode != null && renderNode.isValid()) {
19390                setBackgroundRenderNodeProperties(renderNode);
19391                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
19392                return;
19393            }
19394        }
19395
19396        final int scrollX = mScrollX;
19397        final int scrollY = mScrollY;
19398        if ((scrollX | scrollY) == 0) {
19399            background.draw(canvas);
19400        } else {
19401            canvas.translate(scrollX, scrollY);
19402            background.draw(canvas);
19403            canvas.translate(-scrollX, -scrollY);
19404        }
19405    }
19406
19407    /**
19408     * Sets the correct background bounds and rebuilds the outline, if needed.
19409     * <p/>
19410     * This is called by LayoutLib.
19411     */
19412    void setBackgroundBounds() {
19413        if (mBackgroundSizeChanged && mBackground != null) {
19414            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
19415            mBackgroundSizeChanged = false;
19416            rebuildOutline();
19417        }
19418    }
19419
19420    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
19421        renderNode.setTranslationX(mScrollX);
19422        renderNode.setTranslationY(mScrollY);
19423    }
19424
19425    /**
19426     * Creates a new display list or updates the existing display list for the
19427     * specified Drawable.
19428     *
19429     * @param drawable Drawable for which to create a display list
19430     * @param renderNode Existing RenderNode, or {@code null}
19431     * @return A valid display list for the specified drawable
19432     */
19433    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
19434        if (renderNode == null) {
19435            renderNode = RenderNode.create(drawable.getClass().getName(), this);
19436        }
19437
19438        final Rect bounds = drawable.getBounds();
19439        final int width = bounds.width();
19440        final int height = bounds.height();
19441        final DisplayListCanvas canvas = renderNode.start(width, height);
19442
19443        // Reverse left/top translation done by drawable canvas, which will
19444        // instead be applied by rendernode's LTRB bounds below. This way, the
19445        // drawable's bounds match with its rendernode bounds and its content
19446        // will lie within those bounds in the rendernode tree.
19447        canvas.translate(-bounds.left, -bounds.top);
19448
19449        try {
19450            drawable.draw(canvas);
19451        } finally {
19452            renderNode.end(canvas);
19453        }
19454
19455        // Set up drawable properties that are view-independent.
19456        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
19457        renderNode.setProjectBackwards(drawable.isProjected());
19458        renderNode.setProjectionReceiver(true);
19459        renderNode.setClipToBounds(false);
19460        return renderNode;
19461    }
19462
19463    /**
19464     * Returns the overlay for this view, creating it if it does not yet exist.
19465     * Adding drawables to the overlay will cause them to be displayed whenever
19466     * the view itself is redrawn. Objects in the overlay should be actively
19467     * managed: remove them when they should not be displayed anymore. The
19468     * overlay will always have the same size as its host view.
19469     *
19470     * <p>Note: Overlays do not currently work correctly with {@link
19471     * SurfaceView} or {@link TextureView}; contents in overlays for these
19472     * types of views may not display correctly.</p>
19473     *
19474     * @return The ViewOverlay object for this view.
19475     * @see ViewOverlay
19476     */
19477    public ViewOverlay getOverlay() {
19478        if (mOverlay == null) {
19479            mOverlay = new ViewOverlay(mContext, this);
19480        }
19481        return mOverlay;
19482    }
19483
19484    /**
19485     * Override this if your view is known to always be drawn on top of a solid color background,
19486     * and needs to draw fading edges. Returning a non-zero color enables the view system to
19487     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
19488     * should be set to 0xFF.
19489     *
19490     * @see #setVerticalFadingEdgeEnabled(boolean)
19491     * @see #setHorizontalFadingEdgeEnabled(boolean)
19492     *
19493     * @return The known solid color background for this view, or 0 if the color may vary
19494     */
19495    @ViewDebug.ExportedProperty(category = "drawing")
19496    @ColorInt
19497    public int getSolidColor() {
19498        return 0;
19499    }
19500
19501    /**
19502     * Build a human readable string representation of the specified view flags.
19503     *
19504     * @param flags the view flags to convert to a string
19505     * @return a String representing the supplied flags
19506     */
19507    private static String printFlags(int flags) {
19508        String output = "";
19509        int numFlags = 0;
19510        if ((flags & FOCUSABLE) == FOCUSABLE) {
19511            output += "TAKES_FOCUS";
19512            numFlags++;
19513        }
19514
19515        switch (flags & VISIBILITY_MASK) {
19516        case INVISIBLE:
19517            if (numFlags > 0) {
19518                output += " ";
19519            }
19520            output += "INVISIBLE";
19521            // USELESS HERE numFlags++;
19522            break;
19523        case GONE:
19524            if (numFlags > 0) {
19525                output += " ";
19526            }
19527            output += "GONE";
19528            // USELESS HERE numFlags++;
19529            break;
19530        default:
19531            break;
19532        }
19533        return output;
19534    }
19535
19536    /**
19537     * Build a human readable string representation of the specified private
19538     * view flags.
19539     *
19540     * @param privateFlags the private view flags to convert to a string
19541     * @return a String representing the supplied flags
19542     */
19543    private static String printPrivateFlags(int privateFlags) {
19544        String output = "";
19545        int numFlags = 0;
19546
19547        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
19548            output += "WANTS_FOCUS";
19549            numFlags++;
19550        }
19551
19552        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
19553            if (numFlags > 0) {
19554                output += " ";
19555            }
19556            output += "FOCUSED";
19557            numFlags++;
19558        }
19559
19560        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
19561            if (numFlags > 0) {
19562                output += " ";
19563            }
19564            output += "SELECTED";
19565            numFlags++;
19566        }
19567
19568        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
19569            if (numFlags > 0) {
19570                output += " ";
19571            }
19572            output += "IS_ROOT_NAMESPACE";
19573            numFlags++;
19574        }
19575
19576        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
19577            if (numFlags > 0) {
19578                output += " ";
19579            }
19580            output += "HAS_BOUNDS";
19581            numFlags++;
19582        }
19583
19584        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
19585            if (numFlags > 0) {
19586                output += " ";
19587            }
19588            output += "DRAWN";
19589            // USELESS HERE numFlags++;
19590        }
19591        return output;
19592    }
19593
19594    /**
19595     * <p>Indicates whether or not this view's layout will be requested during
19596     * the next hierarchy layout pass.</p>
19597     *
19598     * @return true if the layout will be forced during next layout pass
19599     */
19600    public boolean isLayoutRequested() {
19601        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19602    }
19603
19604    /**
19605     * Return true if o is a ViewGroup that is laying out using optical bounds.
19606     * @hide
19607     */
19608    public static boolean isLayoutModeOptical(Object o) {
19609        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19610    }
19611
19612    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19613        Insets parentInsets = mParent instanceof View ?
19614                ((View) mParent).getOpticalInsets() : Insets.NONE;
19615        Insets childInsets = getOpticalInsets();
19616        return setFrame(
19617                left   + parentInsets.left - childInsets.left,
19618                top    + parentInsets.top  - childInsets.top,
19619                right  + parentInsets.left + childInsets.right,
19620                bottom + parentInsets.top  + childInsets.bottom);
19621    }
19622
19623    /**
19624     * Assign a size and position to a view and all of its
19625     * descendants
19626     *
19627     * <p>This is the second phase of the layout mechanism.
19628     * (The first is measuring). In this phase, each parent calls
19629     * layout on all of its children to position them.
19630     * This is typically done using the child measurements
19631     * that were stored in the measure pass().</p>
19632     *
19633     * <p>Derived classes should not override this method.
19634     * Derived classes with children should override
19635     * onLayout. In that method, they should
19636     * call layout on each of their children.</p>
19637     *
19638     * @param l Left position, relative to parent
19639     * @param t Top position, relative to parent
19640     * @param r Right position, relative to parent
19641     * @param b Bottom position, relative to parent
19642     */
19643    @SuppressWarnings({"unchecked"})
19644    public void layout(int l, int t, int r, int b) {
19645        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19646            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19647            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19648        }
19649
19650        int oldL = mLeft;
19651        int oldT = mTop;
19652        int oldB = mBottom;
19653        int oldR = mRight;
19654
19655        boolean changed = isLayoutModeOptical(mParent) ?
19656                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19657
19658        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19659            onLayout(changed, l, t, r, b);
19660
19661            if (shouldDrawRoundScrollbar()) {
19662                if(mRoundScrollbarRenderer == null) {
19663                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19664                }
19665            } else {
19666                mRoundScrollbarRenderer = null;
19667            }
19668
19669            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19670
19671            ListenerInfo li = mListenerInfo;
19672            if (li != null && li.mOnLayoutChangeListeners != null) {
19673                ArrayList<OnLayoutChangeListener> listenersCopy =
19674                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19675                int numListeners = listenersCopy.size();
19676                for (int i = 0; i < numListeners; ++i) {
19677                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19678                }
19679            }
19680        }
19681
19682        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19683        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19684
19685        if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
19686            mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
19687            notifyEnterOrExitForAutoFillIfNeeded(true);
19688        }
19689    }
19690
19691    /**
19692     * Called from layout when this view should
19693     * assign a size and position to each of its children.
19694     *
19695     * Derived classes with children should override
19696     * this method and call layout on each of
19697     * their children.
19698     * @param changed This is a new size or position for this view
19699     * @param left Left position, relative to parent
19700     * @param top Top position, relative to parent
19701     * @param right Right position, relative to parent
19702     * @param bottom Bottom position, relative to parent
19703     */
19704    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19705    }
19706
19707    /**
19708     * Assign a size and position to this view.
19709     *
19710     * This is called from layout.
19711     *
19712     * @param left Left position, relative to parent
19713     * @param top Top position, relative to parent
19714     * @param right Right position, relative to parent
19715     * @param bottom Bottom position, relative to parent
19716     * @return true if the new size and position are different than the
19717     *         previous ones
19718     * {@hide}
19719     */
19720    protected boolean setFrame(int left, int top, int right, int bottom) {
19721        boolean changed = false;
19722
19723        if (DBG) {
19724            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19725                    + right + "," + bottom + ")");
19726        }
19727
19728        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19729            changed = true;
19730
19731            // Remember our drawn bit
19732            int drawn = mPrivateFlags & PFLAG_DRAWN;
19733
19734            int oldWidth = mRight - mLeft;
19735            int oldHeight = mBottom - mTop;
19736            int newWidth = right - left;
19737            int newHeight = bottom - top;
19738            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19739
19740            // Invalidate our old position
19741            invalidate(sizeChanged);
19742
19743            mLeft = left;
19744            mTop = top;
19745            mRight = right;
19746            mBottom = bottom;
19747            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19748
19749            mPrivateFlags |= PFLAG_HAS_BOUNDS;
19750
19751
19752            if (sizeChanged) {
19753                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19754            }
19755
19756            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19757                // If we are visible, force the DRAWN bit to on so that
19758                // this invalidate will go through (at least to our parent).
19759                // This is because someone may have invalidated this view
19760                // before this call to setFrame came in, thereby clearing
19761                // the DRAWN bit.
19762                mPrivateFlags |= PFLAG_DRAWN;
19763                invalidate(sizeChanged);
19764                // parent display list may need to be recreated based on a change in the bounds
19765                // of any child
19766                invalidateParentCaches();
19767            }
19768
19769            // Reset drawn bit to original value (invalidate turns it off)
19770            mPrivateFlags |= drawn;
19771
19772            mBackgroundSizeChanged = true;
19773            mDefaultFocusHighlightSizeChanged = true;
19774            if (mForegroundInfo != null) {
19775                mForegroundInfo.mBoundsChanged = true;
19776            }
19777
19778            notifySubtreeAccessibilityStateChangedIfNeeded();
19779        }
19780        return changed;
19781    }
19782
19783    /**
19784     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19785     * @hide
19786     */
19787    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19788        setFrame(left, top, right, bottom);
19789    }
19790
19791    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19792        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19793        if (mOverlay != null) {
19794            mOverlay.getOverlayView().setRight(newWidth);
19795            mOverlay.getOverlayView().setBottom(newHeight);
19796        }
19797        rebuildOutline();
19798    }
19799
19800    /**
19801     * Finalize inflating a view from XML.  This is called as the last phase
19802     * of inflation, after all child views have been added.
19803     *
19804     * <p>Even if the subclass overrides onFinishInflate, they should always be
19805     * sure to call the super method, so that we get called.
19806     */
19807    @CallSuper
19808    protected void onFinishInflate() {
19809    }
19810
19811    /**
19812     * Returns the resources associated with this view.
19813     *
19814     * @return Resources object.
19815     */
19816    public Resources getResources() {
19817        return mResources;
19818    }
19819
19820    /**
19821     * Invalidates the specified Drawable.
19822     *
19823     * @param drawable the drawable to invalidate
19824     */
19825    @Override
19826    public void invalidateDrawable(@NonNull Drawable drawable) {
19827        if (verifyDrawable(drawable)) {
19828            final Rect dirty = drawable.getDirtyBounds();
19829            final int scrollX = mScrollX;
19830            final int scrollY = mScrollY;
19831
19832            invalidate(dirty.left + scrollX, dirty.top + scrollY,
19833                    dirty.right + scrollX, dirty.bottom + scrollY);
19834            rebuildOutline();
19835        }
19836    }
19837
19838    /**
19839     * Schedules an action on a drawable to occur at a specified time.
19840     *
19841     * @param who the recipient of the action
19842     * @param what the action to run on the drawable
19843     * @param when the time at which the action must occur. Uses the
19844     *        {@link SystemClock#uptimeMillis} timebase.
19845     */
19846    @Override
19847    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19848        if (verifyDrawable(who) && what != null) {
19849            final long delay = when - SystemClock.uptimeMillis();
19850            if (mAttachInfo != null) {
19851                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19852                        Choreographer.CALLBACK_ANIMATION, what, who,
19853                        Choreographer.subtractFrameDelay(delay));
19854            } else {
19855                // Postpone the runnable until we know
19856                // on which thread it needs to run.
19857                getRunQueue().postDelayed(what, delay);
19858            }
19859        }
19860    }
19861
19862    /**
19863     * Cancels a scheduled action on a drawable.
19864     *
19865     * @param who the recipient of the action
19866     * @param what the action to cancel
19867     */
19868    @Override
19869    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19870        if (verifyDrawable(who) && what != null) {
19871            if (mAttachInfo != null) {
19872                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19873                        Choreographer.CALLBACK_ANIMATION, what, who);
19874            }
19875            getRunQueue().removeCallbacks(what);
19876        }
19877    }
19878
19879    /**
19880     * Unschedule any events associated with the given Drawable.  This can be
19881     * used when selecting a new Drawable into a view, so that the previous
19882     * one is completely unscheduled.
19883     *
19884     * @param who The Drawable to unschedule.
19885     *
19886     * @see #drawableStateChanged
19887     */
19888    public void unscheduleDrawable(Drawable who) {
19889        if (mAttachInfo != null && who != null) {
19890            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19891                    Choreographer.CALLBACK_ANIMATION, null, who);
19892        }
19893    }
19894
19895    /**
19896     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19897     * that the View directionality can and will be resolved before its Drawables.
19898     *
19899     * Will call {@link View#onResolveDrawables} when resolution is done.
19900     *
19901     * @hide
19902     */
19903    protected void resolveDrawables() {
19904        // Drawables resolution may need to happen before resolving the layout direction (which is
19905        // done only during the measure() call).
19906        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19907        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19908        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19909        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19910        // direction to be resolved as its resolved value will be the same as its raw value.
19911        if (!isLayoutDirectionResolved() &&
19912                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19913            return;
19914        }
19915
19916        final int layoutDirection = isLayoutDirectionResolved() ?
19917                getLayoutDirection() : getRawLayoutDirection();
19918
19919        if (mBackground != null) {
19920            mBackground.setLayoutDirection(layoutDirection);
19921        }
19922        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19923            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19924        }
19925        if (mDefaultFocusHighlight != null) {
19926            mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
19927        }
19928        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19929        onResolveDrawables(layoutDirection);
19930    }
19931
19932    boolean areDrawablesResolved() {
19933        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19934    }
19935
19936    /**
19937     * Called when layout direction has been resolved.
19938     *
19939     * The default implementation does nothing.
19940     *
19941     * @param layoutDirection The resolved layout direction.
19942     *
19943     * @see #LAYOUT_DIRECTION_LTR
19944     * @see #LAYOUT_DIRECTION_RTL
19945     *
19946     * @hide
19947     */
19948    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19949    }
19950
19951    /**
19952     * @hide
19953     */
19954    protected void resetResolvedDrawables() {
19955        resetResolvedDrawablesInternal();
19956    }
19957
19958    void resetResolvedDrawablesInternal() {
19959        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19960    }
19961
19962    /**
19963     * If your view subclass is displaying its own Drawable objects, it should
19964     * override this function and return true for any Drawable it is
19965     * displaying.  This allows animations for those drawables to be
19966     * scheduled.
19967     *
19968     * <p>Be sure to call through to the super class when overriding this
19969     * function.
19970     *
19971     * @param who The Drawable to verify.  Return true if it is one you are
19972     *            displaying, else return the result of calling through to the
19973     *            super class.
19974     *
19975     * @return boolean If true than the Drawable is being displayed in the
19976     *         view; else false and it is not allowed to animate.
19977     *
19978     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19979     * @see #drawableStateChanged()
19980     */
19981    @CallSuper
19982    protected boolean verifyDrawable(@NonNull Drawable who) {
19983        // Avoid verifying the scroll bar drawable so that we don't end up in
19984        // an invalidation loop. This effectively prevents the scroll bar
19985        // drawable from triggering invalidations and scheduling runnables.
19986        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
19987                || (mDefaultFocusHighlight == who);
19988    }
19989
19990    /**
19991     * This function is called whenever the state of the view changes in such
19992     * a way that it impacts the state of drawables being shown.
19993     * <p>
19994     * If the View has a StateListAnimator, it will also be called to run necessary state
19995     * change animations.
19996     * <p>
19997     * Be sure to call through to the superclass when overriding this function.
19998     *
19999     * @see Drawable#setState(int[])
20000     */
20001    @CallSuper
20002    protected void drawableStateChanged() {
20003        final int[] state = getDrawableState();
20004        boolean changed = false;
20005
20006        final Drawable bg = mBackground;
20007        if (bg != null && bg.isStateful()) {
20008            changed |= bg.setState(state);
20009        }
20010
20011        final Drawable hl = mDefaultFocusHighlight;
20012        if (hl != null && hl.isStateful()) {
20013            changed |= hl.setState(state);
20014        }
20015
20016        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20017        if (fg != null && fg.isStateful()) {
20018            changed |= fg.setState(state);
20019        }
20020
20021        if (mScrollCache != null) {
20022            final Drawable scrollBar = mScrollCache.scrollBar;
20023            if (scrollBar != null && scrollBar.isStateful()) {
20024                changed |= scrollBar.setState(state)
20025                        && mScrollCache.state != ScrollabilityCache.OFF;
20026            }
20027        }
20028
20029        if (mStateListAnimator != null) {
20030            mStateListAnimator.setState(state);
20031        }
20032
20033        if (changed) {
20034            invalidate();
20035        }
20036    }
20037
20038    /**
20039     * This function is called whenever the view hotspot changes and needs to
20040     * be propagated to drawables or child views managed by the view.
20041     * <p>
20042     * Dispatching to child views is handled by
20043     * {@link #dispatchDrawableHotspotChanged(float, float)}.
20044     * <p>
20045     * Be sure to call through to the superclass when overriding this function.
20046     *
20047     * @param x hotspot x coordinate
20048     * @param y hotspot y coordinate
20049     */
20050    @CallSuper
20051    public void drawableHotspotChanged(float x, float y) {
20052        if (mBackground != null) {
20053            mBackground.setHotspot(x, y);
20054        }
20055        if (mDefaultFocusHighlight != null) {
20056            mDefaultFocusHighlight.setHotspot(x, y);
20057        }
20058        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
20059            mForegroundInfo.mDrawable.setHotspot(x, y);
20060        }
20061
20062        dispatchDrawableHotspotChanged(x, y);
20063    }
20064
20065    /**
20066     * Dispatches drawableHotspotChanged to all of this View's children.
20067     *
20068     * @param x hotspot x coordinate
20069     * @param y hotspot y coordinate
20070     * @see #drawableHotspotChanged(float, float)
20071     */
20072    public void dispatchDrawableHotspotChanged(float x, float y) {
20073    }
20074
20075    /**
20076     * Call this to force a view to update its drawable state. This will cause
20077     * drawableStateChanged to be called on this view. Views that are interested
20078     * in the new state should call getDrawableState.
20079     *
20080     * @see #drawableStateChanged
20081     * @see #getDrawableState
20082     */
20083    public void refreshDrawableState() {
20084        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
20085        drawableStateChanged();
20086
20087        ViewParent parent = mParent;
20088        if (parent != null) {
20089            parent.childDrawableStateChanged(this);
20090        }
20091    }
20092
20093    /**
20094     * Create a default focus highlight if it doesn't exist.
20095     * @return a default focus highlight.
20096     */
20097    private Drawable getDefaultFocusHighlightDrawable() {
20098        if (mDefaultFocusHighlightCache == null) {
20099            if (mContext != null) {
20100                final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
20101                final TypedArray ta = mContext.obtainStyledAttributes(attrs);
20102                mDefaultFocusHighlightCache = ta.getDrawable(0);
20103                ta.recycle();
20104            }
20105        }
20106        return mDefaultFocusHighlightCache;
20107    }
20108
20109    /**
20110     * Set the current default focus highlight.
20111     * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
20112     */
20113    private void setDefaultFocusHighlight(Drawable highlight) {
20114        mDefaultFocusHighlight = highlight;
20115        mDefaultFocusHighlightSizeChanged = true;
20116        if (highlight != null) {
20117            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20118                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20119            }
20120            highlight.setLayoutDirection(getLayoutDirection());
20121            if (highlight.isStateful()) {
20122                highlight.setState(getDrawableState());
20123            }
20124            if (isAttachedToWindow()) {
20125                highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20126            }
20127            // Set callback last, since the view may still be initializing.
20128            highlight.setCallback(this);
20129        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20130                && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20131            mPrivateFlags |= PFLAG_SKIP_DRAW;
20132        }
20133        invalidate();
20134    }
20135
20136    /**
20137     * Check whether we need to draw a default focus highlight when this view gets focused,
20138     * which requires:
20139     * <ul>
20140     *     <li>In both background and foreground, {@link android.R.attr#state_focused}
20141     *         is not defined.</li>
20142     *     <li>This view is not in touch mode.</li>
20143     *     <li>This view doesn't opt out for a default focus highlight, via
20144     *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
20145     *     <li>This view is attached to window.</li>
20146     * </ul>
20147     * @return {@code true} if a default focus highlight is needed.
20148     * @hide
20149     */
20150    @TestApi
20151    public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
20152        final boolean lackFocusState = (background == null || !background.isStateful()
20153                || !background.hasFocusStateSpecified())
20154                && (foreground == null || !foreground.isStateful()
20155                || !foreground.hasFocusStateSpecified());
20156        return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
20157                && isAttachedToWindow() && sUseDefaultFocusHighlight;
20158    }
20159
20160    /**
20161     * When this view is focused, switches on/off the default focused highlight.
20162     * <p>
20163     * This always happens when this view is focused, and only at this moment the default focus
20164     * highlight can be visible.
20165     */
20166    private void switchDefaultFocusHighlight() {
20167        if (isFocused()) {
20168            final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
20169                    mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
20170            final boolean active = mDefaultFocusHighlight != null;
20171            if (needed && !active) {
20172                setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
20173            } else if (!needed && active) {
20174                // The highlight is no longer needed, so tear it down.
20175                setDefaultFocusHighlight(null);
20176            }
20177        }
20178    }
20179
20180    /**
20181     * Draw the default focus highlight onto the canvas.
20182     * @param canvas the canvas where we're drawing the highlight.
20183     */
20184    private void drawDefaultFocusHighlight(Canvas canvas) {
20185        if (mDefaultFocusHighlight != null) {
20186            if (mDefaultFocusHighlightSizeChanged) {
20187                mDefaultFocusHighlightSizeChanged = false;
20188                final int l = mScrollX;
20189                final int r = l + mRight - mLeft;
20190                final int t = mScrollY;
20191                final int b = t + mBottom - mTop;
20192                mDefaultFocusHighlight.setBounds(l, t, r, b);
20193            }
20194            mDefaultFocusHighlight.draw(canvas);
20195        }
20196    }
20197
20198    /**
20199     * Return an array of resource IDs of the drawable states representing the
20200     * current state of the view.
20201     *
20202     * @return The current drawable state
20203     *
20204     * @see Drawable#setState(int[])
20205     * @see #drawableStateChanged()
20206     * @see #onCreateDrawableState(int)
20207     */
20208    public final int[] getDrawableState() {
20209        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
20210            return mDrawableState;
20211        } else {
20212            mDrawableState = onCreateDrawableState(0);
20213            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
20214            return mDrawableState;
20215        }
20216    }
20217
20218    /**
20219     * Generate the new {@link android.graphics.drawable.Drawable} state for
20220     * this view. This is called by the view
20221     * system when the cached Drawable state is determined to be invalid.  To
20222     * retrieve the current state, you should use {@link #getDrawableState}.
20223     *
20224     * @param extraSpace if non-zero, this is the number of extra entries you
20225     * would like in the returned array in which you can place your own
20226     * states.
20227     *
20228     * @return Returns an array holding the current {@link Drawable} state of
20229     * the view.
20230     *
20231     * @see #mergeDrawableStates(int[], int[])
20232     */
20233    protected int[] onCreateDrawableState(int extraSpace) {
20234        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
20235                mParent instanceof View) {
20236            return ((View) mParent).onCreateDrawableState(extraSpace);
20237        }
20238
20239        int[] drawableState;
20240
20241        int privateFlags = mPrivateFlags;
20242
20243        int viewStateIndex = 0;
20244        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
20245        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
20246        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
20247        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
20248        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
20249        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
20250        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
20251                ThreadedRenderer.isAvailable()) {
20252            // This is set if HW acceleration is requested, even if the current
20253            // process doesn't allow it.  This is just to allow app preview
20254            // windows to better match their app.
20255            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
20256        }
20257        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
20258
20259        final int privateFlags2 = mPrivateFlags2;
20260        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
20261            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
20262        }
20263        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
20264            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
20265        }
20266
20267        drawableState = StateSet.get(viewStateIndex);
20268
20269        //noinspection ConstantIfStatement
20270        if (false) {
20271            Log.i("View", "drawableStateIndex=" + viewStateIndex);
20272            Log.i("View", toString()
20273                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
20274                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
20275                    + " fo=" + hasFocus()
20276                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
20277                    + " wf=" + hasWindowFocus()
20278                    + ": " + Arrays.toString(drawableState));
20279        }
20280
20281        if (extraSpace == 0) {
20282            return drawableState;
20283        }
20284
20285        final int[] fullState;
20286        if (drawableState != null) {
20287            fullState = new int[drawableState.length + extraSpace];
20288            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
20289        } else {
20290            fullState = new int[extraSpace];
20291        }
20292
20293        return fullState;
20294    }
20295
20296    /**
20297     * Merge your own state values in <var>additionalState</var> into the base
20298     * state values <var>baseState</var> that were returned by
20299     * {@link #onCreateDrawableState(int)}.
20300     *
20301     * @param baseState The base state values returned by
20302     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
20303     * own additional state values.
20304     *
20305     * @param additionalState The additional state values you would like
20306     * added to <var>baseState</var>; this array is not modified.
20307     *
20308     * @return As a convenience, the <var>baseState</var> array you originally
20309     * passed into the function is returned.
20310     *
20311     * @see #onCreateDrawableState(int)
20312     */
20313    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
20314        final int N = baseState.length;
20315        int i = N - 1;
20316        while (i >= 0 && baseState[i] == 0) {
20317            i--;
20318        }
20319        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
20320        return baseState;
20321    }
20322
20323    /**
20324     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
20325     * on all Drawable objects associated with this view.
20326     * <p>
20327     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
20328     * attached to this view.
20329     */
20330    @CallSuper
20331    public void jumpDrawablesToCurrentState() {
20332        if (mBackground != null) {
20333            mBackground.jumpToCurrentState();
20334        }
20335        if (mStateListAnimator != null) {
20336            mStateListAnimator.jumpToCurrentState();
20337        }
20338        if (mDefaultFocusHighlight != null) {
20339            mDefaultFocusHighlight.jumpToCurrentState();
20340        }
20341        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
20342            mForegroundInfo.mDrawable.jumpToCurrentState();
20343        }
20344    }
20345
20346    /**
20347     * Sets the background color for this view.
20348     * @param color the color of the background
20349     */
20350    @RemotableViewMethod
20351    public void setBackgroundColor(@ColorInt int color) {
20352        if (mBackground instanceof ColorDrawable) {
20353            ((ColorDrawable) mBackground.mutate()).setColor(color);
20354            computeOpaqueFlags();
20355            mBackgroundResource = 0;
20356        } else {
20357            setBackground(new ColorDrawable(color));
20358        }
20359    }
20360
20361    /**
20362     * Set the background to a given resource. The resource should refer to
20363     * a Drawable object or 0 to remove the background.
20364     * @param resid The identifier of the resource.
20365     *
20366     * @attr ref android.R.styleable#View_background
20367     */
20368    @RemotableViewMethod
20369    public void setBackgroundResource(@DrawableRes int resid) {
20370        if (resid != 0 && resid == mBackgroundResource) {
20371            return;
20372        }
20373
20374        Drawable d = null;
20375        if (resid != 0) {
20376            d = mContext.getDrawable(resid);
20377        }
20378        setBackground(d);
20379
20380        mBackgroundResource = resid;
20381    }
20382
20383    /**
20384     * Set the background to a given Drawable, or remove the background. If the
20385     * background has padding, this View's padding is set to the background's
20386     * padding. However, when a background is removed, this View's padding isn't
20387     * touched. If setting the padding is desired, please use
20388     * {@link #setPadding(int, int, int, int)}.
20389     *
20390     * @param background The Drawable to use as the background, or null to remove the
20391     *        background
20392     */
20393    public void setBackground(Drawable background) {
20394        //noinspection deprecation
20395        setBackgroundDrawable(background);
20396    }
20397
20398    /**
20399     * @deprecated use {@link #setBackground(Drawable)} instead
20400     */
20401    @Deprecated
20402    public void setBackgroundDrawable(Drawable background) {
20403        computeOpaqueFlags();
20404
20405        if (background == mBackground) {
20406            return;
20407        }
20408
20409        boolean requestLayout = false;
20410
20411        mBackgroundResource = 0;
20412
20413        /*
20414         * Regardless of whether we're setting a new background or not, we want
20415         * to clear the previous drawable. setVisible first while we still have the callback set.
20416         */
20417        if (mBackground != null) {
20418            if (isAttachedToWindow()) {
20419                mBackground.setVisible(false, false);
20420            }
20421            mBackground.setCallback(null);
20422            unscheduleDrawable(mBackground);
20423        }
20424
20425        if (background != null) {
20426            Rect padding = sThreadLocal.get();
20427            if (padding == null) {
20428                padding = new Rect();
20429                sThreadLocal.set(padding);
20430            }
20431            resetResolvedDrawablesInternal();
20432            background.setLayoutDirection(getLayoutDirection());
20433            if (background.getPadding(padding)) {
20434                resetResolvedPaddingInternal();
20435                switch (background.getLayoutDirection()) {
20436                    case LAYOUT_DIRECTION_RTL:
20437                        mUserPaddingLeftInitial = padding.right;
20438                        mUserPaddingRightInitial = padding.left;
20439                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
20440                        break;
20441                    case LAYOUT_DIRECTION_LTR:
20442                    default:
20443                        mUserPaddingLeftInitial = padding.left;
20444                        mUserPaddingRightInitial = padding.right;
20445                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
20446                }
20447                mLeftPaddingDefined = false;
20448                mRightPaddingDefined = false;
20449            }
20450
20451            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
20452            // if it has a different minimum size, we should layout again
20453            if (mBackground == null
20454                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
20455                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
20456                requestLayout = true;
20457            }
20458
20459            // Set mBackground before we set this as the callback and start making other
20460            // background drawable state change calls. In particular, the setVisible call below
20461            // can result in drawables attempting to start animations or otherwise invalidate,
20462            // which requires the view set as the callback (us) to recognize the drawable as
20463            // belonging to it as per verifyDrawable.
20464            mBackground = background;
20465            if (background.isStateful()) {
20466                background.setState(getDrawableState());
20467            }
20468            if (isAttachedToWindow()) {
20469                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20470            }
20471
20472            applyBackgroundTint();
20473
20474            // Set callback last, since the view may still be initializing.
20475            background.setCallback(this);
20476
20477            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20478                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20479                requestLayout = true;
20480            }
20481        } else {
20482            /* Remove the background */
20483            mBackground = null;
20484            if ((mViewFlags & WILL_NOT_DRAW) != 0
20485                    && (mDefaultFocusHighlight == null)
20486                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20487                mPrivateFlags |= PFLAG_SKIP_DRAW;
20488            }
20489
20490            /*
20491             * When the background is set, we try to apply its padding to this
20492             * View. When the background is removed, we don't touch this View's
20493             * padding. This is noted in the Javadocs. Hence, we don't need to
20494             * requestLayout(), the invalidate() below is sufficient.
20495             */
20496
20497            // The old background's minimum size could have affected this
20498            // View's layout, so let's requestLayout
20499            requestLayout = true;
20500        }
20501
20502        computeOpaqueFlags();
20503
20504        if (requestLayout) {
20505            requestLayout();
20506        }
20507
20508        mBackgroundSizeChanged = true;
20509        invalidate(true);
20510        invalidateOutline();
20511    }
20512
20513    /**
20514     * Gets the background drawable
20515     *
20516     * @return The drawable used as the background for this view, if any.
20517     *
20518     * @see #setBackground(Drawable)
20519     *
20520     * @attr ref android.R.styleable#View_background
20521     */
20522    public Drawable getBackground() {
20523        return mBackground;
20524    }
20525
20526    /**
20527     * Applies a tint to the background drawable. Does not modify the current tint
20528     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20529     * <p>
20530     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
20531     * mutate the drawable and apply the specified tint and tint mode using
20532     * {@link Drawable#setTintList(ColorStateList)}.
20533     *
20534     * @param tint the tint to apply, may be {@code null} to clear tint
20535     *
20536     * @attr ref android.R.styleable#View_backgroundTint
20537     * @see #getBackgroundTintList()
20538     * @see Drawable#setTintList(ColorStateList)
20539     */
20540    public void setBackgroundTintList(@Nullable ColorStateList tint) {
20541        if (mBackgroundTint == null) {
20542            mBackgroundTint = new TintInfo();
20543        }
20544        mBackgroundTint.mTintList = tint;
20545        mBackgroundTint.mHasTintList = true;
20546
20547        applyBackgroundTint();
20548    }
20549
20550    /**
20551     * Return the tint applied to the background drawable, if specified.
20552     *
20553     * @return the tint applied to the background drawable
20554     * @attr ref android.R.styleable#View_backgroundTint
20555     * @see #setBackgroundTintList(ColorStateList)
20556     */
20557    @Nullable
20558    public ColorStateList getBackgroundTintList() {
20559        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
20560    }
20561
20562    /**
20563     * Specifies the blending mode used to apply the tint specified by
20564     * {@link #setBackgroundTintList(ColorStateList)}} to the background
20565     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20566     *
20567     * @param tintMode the blending mode used to apply the tint, may be
20568     *                 {@code null} to clear tint
20569     * @attr ref android.R.styleable#View_backgroundTintMode
20570     * @see #getBackgroundTintMode()
20571     * @see Drawable#setTintMode(PorterDuff.Mode)
20572     */
20573    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20574        if (mBackgroundTint == null) {
20575            mBackgroundTint = new TintInfo();
20576        }
20577        mBackgroundTint.mTintMode = tintMode;
20578        mBackgroundTint.mHasTintMode = true;
20579
20580        applyBackgroundTint();
20581    }
20582
20583    /**
20584     * Return the blending mode used to apply the tint to the background
20585     * drawable, if specified.
20586     *
20587     * @return the blending mode used to apply the tint to the background
20588     *         drawable
20589     * @attr ref android.R.styleable#View_backgroundTintMode
20590     * @see #setBackgroundTintMode(PorterDuff.Mode)
20591     */
20592    @Nullable
20593    public PorterDuff.Mode getBackgroundTintMode() {
20594        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
20595    }
20596
20597    private void applyBackgroundTint() {
20598        if (mBackground != null && mBackgroundTint != null) {
20599            final TintInfo tintInfo = mBackgroundTint;
20600            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20601                mBackground = mBackground.mutate();
20602
20603                if (tintInfo.mHasTintList) {
20604                    mBackground.setTintList(tintInfo.mTintList);
20605                }
20606
20607                if (tintInfo.mHasTintMode) {
20608                    mBackground.setTintMode(tintInfo.mTintMode);
20609                }
20610
20611                // The drawable (or one of its children) may not have been
20612                // stateful before applying the tint, so let's try again.
20613                if (mBackground.isStateful()) {
20614                    mBackground.setState(getDrawableState());
20615                }
20616            }
20617        }
20618    }
20619
20620    /**
20621     * Returns the drawable used as the foreground of this View. The
20622     * foreground drawable, if non-null, is always drawn on top of the view's content.
20623     *
20624     * @return a Drawable or null if no foreground was set
20625     *
20626     * @see #onDrawForeground(Canvas)
20627     */
20628    public Drawable getForeground() {
20629        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20630    }
20631
20632    /**
20633     * Supply a Drawable that is to be rendered on top of all of the content in the view.
20634     *
20635     * @param foreground the Drawable to be drawn on top of the children
20636     *
20637     * @attr ref android.R.styleable#View_foreground
20638     */
20639    public void setForeground(Drawable foreground) {
20640        if (mForegroundInfo == null) {
20641            if (foreground == null) {
20642                // Nothing to do.
20643                return;
20644            }
20645            mForegroundInfo = new ForegroundInfo();
20646        }
20647
20648        if (foreground == mForegroundInfo.mDrawable) {
20649            // Nothing to do
20650            return;
20651        }
20652
20653        if (mForegroundInfo.mDrawable != null) {
20654            if (isAttachedToWindow()) {
20655                mForegroundInfo.mDrawable.setVisible(false, false);
20656            }
20657            mForegroundInfo.mDrawable.setCallback(null);
20658            unscheduleDrawable(mForegroundInfo.mDrawable);
20659        }
20660
20661        mForegroundInfo.mDrawable = foreground;
20662        mForegroundInfo.mBoundsChanged = true;
20663        if (foreground != null) {
20664            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20665                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20666            }
20667            foreground.setLayoutDirection(getLayoutDirection());
20668            if (foreground.isStateful()) {
20669                foreground.setState(getDrawableState());
20670            }
20671            applyForegroundTint();
20672            if (isAttachedToWindow()) {
20673                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20674            }
20675            // Set callback last, since the view may still be initializing.
20676            foreground.setCallback(this);
20677        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20678                && (mDefaultFocusHighlight == null)) {
20679            mPrivateFlags |= PFLAG_SKIP_DRAW;
20680        }
20681        requestLayout();
20682        invalidate();
20683    }
20684
20685    /**
20686     * Magic bit used to support features of framework-internal window decor implementation details.
20687     * This used to live exclusively in FrameLayout.
20688     *
20689     * @return true if the foreground should draw inside the padding region or false
20690     *         if it should draw inset by the view's padding
20691     * @hide internal use only; only used by FrameLayout and internal screen layouts.
20692     */
20693    public boolean isForegroundInsidePadding() {
20694        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
20695    }
20696
20697    /**
20698     * Describes how the foreground is positioned.
20699     *
20700     * @return foreground gravity.
20701     *
20702     * @see #setForegroundGravity(int)
20703     *
20704     * @attr ref android.R.styleable#View_foregroundGravity
20705     */
20706    public int getForegroundGravity() {
20707        return mForegroundInfo != null ? mForegroundInfo.mGravity
20708                : Gravity.START | Gravity.TOP;
20709    }
20710
20711    /**
20712     * Describes how the foreground is positioned. Defaults to START and TOP.
20713     *
20714     * @param gravity see {@link android.view.Gravity}
20715     *
20716     * @see #getForegroundGravity()
20717     *
20718     * @attr ref android.R.styleable#View_foregroundGravity
20719     */
20720    public void setForegroundGravity(int gravity) {
20721        if (mForegroundInfo == null) {
20722            mForegroundInfo = new ForegroundInfo();
20723        }
20724
20725        if (mForegroundInfo.mGravity != gravity) {
20726            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20727                gravity |= Gravity.START;
20728            }
20729
20730            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20731                gravity |= Gravity.TOP;
20732            }
20733
20734            mForegroundInfo.mGravity = gravity;
20735            requestLayout();
20736        }
20737    }
20738
20739    /**
20740     * Applies a tint to the foreground drawable. Does not modify the current tint
20741     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20742     * <p>
20743     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20744     * mutate the drawable and apply the specified tint and tint mode using
20745     * {@link Drawable#setTintList(ColorStateList)}.
20746     *
20747     * @param tint the tint to apply, may be {@code null} to clear tint
20748     *
20749     * @attr ref android.R.styleable#View_foregroundTint
20750     * @see #getForegroundTintList()
20751     * @see Drawable#setTintList(ColorStateList)
20752     */
20753    public void setForegroundTintList(@Nullable ColorStateList tint) {
20754        if (mForegroundInfo == null) {
20755            mForegroundInfo = new ForegroundInfo();
20756        }
20757        if (mForegroundInfo.mTintInfo == null) {
20758            mForegroundInfo.mTintInfo = new TintInfo();
20759        }
20760        mForegroundInfo.mTintInfo.mTintList = tint;
20761        mForegroundInfo.mTintInfo.mHasTintList = true;
20762
20763        applyForegroundTint();
20764    }
20765
20766    /**
20767     * Return the tint applied to the foreground drawable, if specified.
20768     *
20769     * @return the tint applied to the foreground drawable
20770     * @attr ref android.R.styleable#View_foregroundTint
20771     * @see #setForegroundTintList(ColorStateList)
20772     */
20773    @Nullable
20774    public ColorStateList getForegroundTintList() {
20775        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20776                ? mForegroundInfo.mTintInfo.mTintList : null;
20777    }
20778
20779    /**
20780     * Specifies the blending mode used to apply the tint specified by
20781     * {@link #setForegroundTintList(ColorStateList)}} to the background
20782     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20783     *
20784     * @param tintMode the blending mode used to apply the tint, may be
20785     *                 {@code null} to clear tint
20786     * @attr ref android.R.styleable#View_foregroundTintMode
20787     * @see #getForegroundTintMode()
20788     * @see Drawable#setTintMode(PorterDuff.Mode)
20789     */
20790    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20791        if (mForegroundInfo == null) {
20792            mForegroundInfo = new ForegroundInfo();
20793        }
20794        if (mForegroundInfo.mTintInfo == null) {
20795            mForegroundInfo.mTintInfo = new TintInfo();
20796        }
20797        mForegroundInfo.mTintInfo.mTintMode = tintMode;
20798        mForegroundInfo.mTintInfo.mHasTintMode = true;
20799
20800        applyForegroundTint();
20801    }
20802
20803    /**
20804     * Return the blending mode used to apply the tint to the foreground
20805     * drawable, if specified.
20806     *
20807     * @return the blending mode used to apply the tint to the foreground
20808     *         drawable
20809     * @attr ref android.R.styleable#View_foregroundTintMode
20810     * @see #setForegroundTintMode(PorterDuff.Mode)
20811     */
20812    @Nullable
20813    public PorterDuff.Mode getForegroundTintMode() {
20814        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20815                ? mForegroundInfo.mTintInfo.mTintMode : null;
20816    }
20817
20818    private void applyForegroundTint() {
20819        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20820                && mForegroundInfo.mTintInfo != null) {
20821            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20822            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20823                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20824
20825                if (tintInfo.mHasTintList) {
20826                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20827                }
20828
20829                if (tintInfo.mHasTintMode) {
20830                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20831                }
20832
20833                // The drawable (or one of its children) may not have been
20834                // stateful before applying the tint, so let's try again.
20835                if (mForegroundInfo.mDrawable.isStateful()) {
20836                    mForegroundInfo.mDrawable.setState(getDrawableState());
20837                }
20838            }
20839        }
20840    }
20841
20842    /**
20843     * Get the drawable to be overlayed when a view is autofilled
20844     *
20845     * @return The drawable
20846     *
20847     * @throws IllegalStateException if the drawable could not be found.
20848     */
20849    @Nullable private Drawable getAutofilledDrawable() {
20850        if (mAttachInfo == null) {
20851            return null;
20852        }
20853        // Lazily load the isAutofilled drawable.
20854        if (mAttachInfo.mAutofilledDrawable == null) {
20855            Context rootContext = getRootView().getContext();
20856            TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
20857            int attributeResourceId = a.getResourceId(0, 0);
20858            mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
20859            a.recycle();
20860        }
20861
20862        return mAttachInfo.mAutofilledDrawable;
20863    }
20864
20865    /**
20866     * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
20867     *
20868     * @param canvas The canvas to draw on
20869     */
20870    private void drawAutofilledHighlight(@NonNull Canvas canvas) {
20871        if (isAutofilled()) {
20872            Drawable autofilledHighlight = getAutofilledDrawable();
20873
20874            if (autofilledHighlight != null) {
20875                autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
20876                autofilledHighlight.draw(canvas);
20877            }
20878        }
20879    }
20880
20881    /**
20882     * Draw any foreground content for this view.
20883     *
20884     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20885     * drawable or other view-specific decorations. The foreground is drawn on top of the
20886     * primary view content.</p>
20887     *
20888     * @param canvas canvas to draw into
20889     */
20890    public void onDrawForeground(Canvas canvas) {
20891        onDrawScrollIndicators(canvas);
20892        onDrawScrollBars(canvas);
20893
20894        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20895        if (foreground != null) {
20896            if (mForegroundInfo.mBoundsChanged) {
20897                mForegroundInfo.mBoundsChanged = false;
20898                final Rect selfBounds = mForegroundInfo.mSelfBounds;
20899                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20900
20901                if (mForegroundInfo.mInsidePadding) {
20902                    selfBounds.set(0, 0, getWidth(), getHeight());
20903                } else {
20904                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
20905                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20906                }
20907
20908                final int ld = getLayoutDirection();
20909                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20910                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20911                foreground.setBounds(overlayBounds);
20912            }
20913
20914            foreground.draw(canvas);
20915        }
20916    }
20917
20918    /**
20919     * Sets the padding. The view may add on the space required to display
20920     * the scrollbars, depending on the style and visibility of the scrollbars.
20921     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20922     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20923     * from the values set in this call.
20924     *
20925     * @attr ref android.R.styleable#View_padding
20926     * @attr ref android.R.styleable#View_paddingBottom
20927     * @attr ref android.R.styleable#View_paddingLeft
20928     * @attr ref android.R.styleable#View_paddingRight
20929     * @attr ref android.R.styleable#View_paddingTop
20930     * @param left the left padding in pixels
20931     * @param top the top padding in pixels
20932     * @param right the right padding in pixels
20933     * @param bottom the bottom padding in pixels
20934     */
20935    public void setPadding(int left, int top, int right, int bottom) {
20936        resetResolvedPaddingInternal();
20937
20938        mUserPaddingStart = UNDEFINED_PADDING;
20939        mUserPaddingEnd = UNDEFINED_PADDING;
20940
20941        mUserPaddingLeftInitial = left;
20942        mUserPaddingRightInitial = right;
20943
20944        mLeftPaddingDefined = true;
20945        mRightPaddingDefined = true;
20946
20947        internalSetPadding(left, top, right, bottom);
20948    }
20949
20950    /**
20951     * @hide
20952     */
20953    protected void internalSetPadding(int left, int top, int right, int bottom) {
20954        mUserPaddingLeft = left;
20955        mUserPaddingRight = right;
20956        mUserPaddingBottom = bottom;
20957
20958        final int viewFlags = mViewFlags;
20959        boolean changed = false;
20960
20961        // Common case is there are no scroll bars.
20962        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20963            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20964                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20965                        ? 0 : getVerticalScrollbarWidth();
20966                switch (mVerticalScrollbarPosition) {
20967                    case SCROLLBAR_POSITION_DEFAULT:
20968                        if (isLayoutRtl()) {
20969                            left += offset;
20970                        } else {
20971                            right += offset;
20972                        }
20973                        break;
20974                    case SCROLLBAR_POSITION_RIGHT:
20975                        right += offset;
20976                        break;
20977                    case SCROLLBAR_POSITION_LEFT:
20978                        left += offset;
20979                        break;
20980                }
20981            }
20982            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20983                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20984                        ? 0 : getHorizontalScrollbarHeight();
20985            }
20986        }
20987
20988        if (mPaddingLeft != left) {
20989            changed = true;
20990            mPaddingLeft = left;
20991        }
20992        if (mPaddingTop != top) {
20993            changed = true;
20994            mPaddingTop = top;
20995        }
20996        if (mPaddingRight != right) {
20997            changed = true;
20998            mPaddingRight = right;
20999        }
21000        if (mPaddingBottom != bottom) {
21001            changed = true;
21002            mPaddingBottom = bottom;
21003        }
21004
21005        if (changed) {
21006            requestLayout();
21007            invalidateOutline();
21008        }
21009    }
21010
21011    /**
21012     * Sets the relative padding. The view may add on the space required to display
21013     * the scrollbars, depending on the style and visibility of the scrollbars.
21014     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
21015     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
21016     * from the values set in this call.
21017     *
21018     * @attr ref android.R.styleable#View_padding
21019     * @attr ref android.R.styleable#View_paddingBottom
21020     * @attr ref android.R.styleable#View_paddingStart
21021     * @attr ref android.R.styleable#View_paddingEnd
21022     * @attr ref android.R.styleable#View_paddingTop
21023     * @param start the start padding in pixels
21024     * @param top the top padding in pixels
21025     * @param end the end padding in pixels
21026     * @param bottom the bottom padding in pixels
21027     */
21028    public void setPaddingRelative(int start, int top, int end, int bottom) {
21029        resetResolvedPaddingInternal();
21030
21031        mUserPaddingStart = start;
21032        mUserPaddingEnd = end;
21033        mLeftPaddingDefined = true;
21034        mRightPaddingDefined = true;
21035
21036        switch(getLayoutDirection()) {
21037            case LAYOUT_DIRECTION_RTL:
21038                mUserPaddingLeftInitial = end;
21039                mUserPaddingRightInitial = start;
21040                internalSetPadding(end, top, start, bottom);
21041                break;
21042            case LAYOUT_DIRECTION_LTR:
21043            default:
21044                mUserPaddingLeftInitial = start;
21045                mUserPaddingRightInitial = end;
21046                internalSetPadding(start, top, end, bottom);
21047        }
21048    }
21049
21050    /**
21051     * Returns the top padding of this view.
21052     *
21053     * @return the top padding in pixels
21054     */
21055    public int getPaddingTop() {
21056        return mPaddingTop;
21057    }
21058
21059    /**
21060     * Returns the bottom padding of this view. If there are inset and enabled
21061     * scrollbars, this value may include the space required to display the
21062     * scrollbars as well.
21063     *
21064     * @return the bottom padding in pixels
21065     */
21066    public int getPaddingBottom() {
21067        return mPaddingBottom;
21068    }
21069
21070    /**
21071     * Returns the left padding of this view. If there are inset and enabled
21072     * scrollbars, this value may include the space required to display the
21073     * scrollbars as well.
21074     *
21075     * @return the left padding in pixels
21076     */
21077    public int getPaddingLeft() {
21078        if (!isPaddingResolved()) {
21079            resolvePadding();
21080        }
21081        return mPaddingLeft;
21082    }
21083
21084    /**
21085     * Returns the start padding of this view depending on its resolved layout direction.
21086     * If there are inset and enabled scrollbars, this value may include the space
21087     * required to display the scrollbars as well.
21088     *
21089     * @return the start padding in pixels
21090     */
21091    public int getPaddingStart() {
21092        if (!isPaddingResolved()) {
21093            resolvePadding();
21094        }
21095        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
21096                mPaddingRight : mPaddingLeft;
21097    }
21098
21099    /**
21100     * Returns the right padding of this view. If there are inset and enabled
21101     * scrollbars, this value may include the space required to display the
21102     * scrollbars as well.
21103     *
21104     * @return the right padding in pixels
21105     */
21106    public int getPaddingRight() {
21107        if (!isPaddingResolved()) {
21108            resolvePadding();
21109        }
21110        return mPaddingRight;
21111    }
21112
21113    /**
21114     * Returns the end padding of this view depending on its resolved layout direction.
21115     * If there are inset and enabled scrollbars, this value may include the space
21116     * required to display the scrollbars as well.
21117     *
21118     * @return the end padding in pixels
21119     */
21120    public int getPaddingEnd() {
21121        if (!isPaddingResolved()) {
21122            resolvePadding();
21123        }
21124        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
21125                mPaddingLeft : mPaddingRight;
21126    }
21127
21128    /**
21129     * Return if the padding has been set through relative values
21130     * {@link #setPaddingRelative(int, int, int, int)} or through
21131     * @attr ref android.R.styleable#View_paddingStart or
21132     * @attr ref android.R.styleable#View_paddingEnd
21133     *
21134     * @return true if the padding is relative or false if it is not.
21135     */
21136    public boolean isPaddingRelative() {
21137        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
21138    }
21139
21140    Insets computeOpticalInsets() {
21141        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
21142    }
21143
21144    /**
21145     * @hide
21146     */
21147    public void resetPaddingToInitialValues() {
21148        if (isRtlCompatibilityMode()) {
21149            mPaddingLeft = mUserPaddingLeftInitial;
21150            mPaddingRight = mUserPaddingRightInitial;
21151            return;
21152        }
21153        if (isLayoutRtl()) {
21154            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
21155            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
21156        } else {
21157            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
21158            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
21159        }
21160    }
21161
21162    /**
21163     * @hide
21164     */
21165    public Insets getOpticalInsets() {
21166        if (mLayoutInsets == null) {
21167            mLayoutInsets = computeOpticalInsets();
21168        }
21169        return mLayoutInsets;
21170    }
21171
21172    /**
21173     * Set this view's optical insets.
21174     *
21175     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
21176     * property. Views that compute their own optical insets should call it as part of measurement.
21177     * This method does not request layout. If you are setting optical insets outside of
21178     * measure/layout itself you will want to call requestLayout() yourself.
21179     * </p>
21180     * @hide
21181     */
21182    public void setOpticalInsets(Insets insets) {
21183        mLayoutInsets = insets;
21184    }
21185
21186    /**
21187     * Changes the selection state of this view. A view can be selected or not.
21188     * Note that selection is not the same as focus. Views are typically
21189     * selected in the context of an AdapterView like ListView or GridView;
21190     * the selected view is the view that is highlighted.
21191     *
21192     * @param selected true if the view must be selected, false otherwise
21193     */
21194    public void setSelected(boolean selected) {
21195        //noinspection DoubleNegation
21196        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
21197            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
21198            if (!selected) resetPressedState();
21199            invalidate(true);
21200            refreshDrawableState();
21201            dispatchSetSelected(selected);
21202            if (selected) {
21203                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
21204            } else {
21205                notifyViewAccessibilityStateChangedIfNeeded(
21206                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
21207            }
21208        }
21209    }
21210
21211    /**
21212     * Dispatch setSelected to all of this View's children.
21213     *
21214     * @see #setSelected(boolean)
21215     *
21216     * @param selected The new selected state
21217     */
21218    protected void dispatchSetSelected(boolean selected) {
21219    }
21220
21221    /**
21222     * Indicates the selection state of this view.
21223     *
21224     * @return true if the view is selected, false otherwise
21225     */
21226    @ViewDebug.ExportedProperty
21227    public boolean isSelected() {
21228        return (mPrivateFlags & PFLAG_SELECTED) != 0;
21229    }
21230
21231    /**
21232     * Changes the activated state of this view. A view can be activated or not.
21233     * Note that activation is not the same as selection.  Selection is
21234     * a transient property, representing the view (hierarchy) the user is
21235     * currently interacting with.  Activation is a longer-term state that the
21236     * user can move views in and out of.  For example, in a list view with
21237     * single or multiple selection enabled, the views in the current selection
21238     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
21239     * here.)  The activated state is propagated down to children of the view it
21240     * is set on.
21241     *
21242     * @param activated true if the view must be activated, false otherwise
21243     */
21244    public void setActivated(boolean activated) {
21245        //noinspection DoubleNegation
21246        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
21247            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
21248            invalidate(true);
21249            refreshDrawableState();
21250            dispatchSetActivated(activated);
21251        }
21252    }
21253
21254    /**
21255     * Dispatch setActivated to all of this View's children.
21256     *
21257     * @see #setActivated(boolean)
21258     *
21259     * @param activated The new activated state
21260     */
21261    protected void dispatchSetActivated(boolean activated) {
21262    }
21263
21264    /**
21265     * Indicates the activation state of this view.
21266     *
21267     * @return true if the view is activated, false otherwise
21268     */
21269    @ViewDebug.ExportedProperty
21270    public boolean isActivated() {
21271        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
21272    }
21273
21274    /**
21275     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
21276     * observer can be used to get notifications when global events, like
21277     * layout, happen.
21278     *
21279     * The returned ViewTreeObserver observer is not guaranteed to remain
21280     * valid for the lifetime of this View. If the caller of this method keeps
21281     * a long-lived reference to ViewTreeObserver, it should always check for
21282     * the return value of {@link ViewTreeObserver#isAlive()}.
21283     *
21284     * @return The ViewTreeObserver for this view's hierarchy.
21285     */
21286    public ViewTreeObserver getViewTreeObserver() {
21287        if (mAttachInfo != null) {
21288            return mAttachInfo.mTreeObserver;
21289        }
21290        if (mFloatingTreeObserver == null) {
21291            mFloatingTreeObserver = new ViewTreeObserver(mContext);
21292        }
21293        return mFloatingTreeObserver;
21294    }
21295
21296    /**
21297     * <p>Finds the topmost view in the current view hierarchy.</p>
21298     *
21299     * @return the topmost view containing this view
21300     */
21301    public View getRootView() {
21302        if (mAttachInfo != null) {
21303            final View v = mAttachInfo.mRootView;
21304            if (v != null) {
21305                return v;
21306            }
21307        }
21308
21309        View parent = this;
21310
21311        while (parent.mParent != null && parent.mParent instanceof View) {
21312            parent = (View) parent.mParent;
21313        }
21314
21315        return parent;
21316    }
21317
21318    /**
21319     * Transforms a motion event from view-local coordinates to on-screen
21320     * coordinates.
21321     *
21322     * @param ev the view-local motion event
21323     * @return false if the transformation could not be applied
21324     * @hide
21325     */
21326    public boolean toGlobalMotionEvent(MotionEvent ev) {
21327        final AttachInfo info = mAttachInfo;
21328        if (info == null) {
21329            return false;
21330        }
21331
21332        final Matrix m = info.mTmpMatrix;
21333        m.set(Matrix.IDENTITY_MATRIX);
21334        transformMatrixToGlobal(m);
21335        ev.transform(m);
21336        return true;
21337    }
21338
21339    /**
21340     * Transforms a motion event from on-screen coordinates to view-local
21341     * coordinates.
21342     *
21343     * @param ev the on-screen motion event
21344     * @return false if the transformation could not be applied
21345     * @hide
21346     */
21347    public boolean toLocalMotionEvent(MotionEvent ev) {
21348        final AttachInfo info = mAttachInfo;
21349        if (info == null) {
21350            return false;
21351        }
21352
21353        final Matrix m = info.mTmpMatrix;
21354        m.set(Matrix.IDENTITY_MATRIX);
21355        transformMatrixToLocal(m);
21356        ev.transform(m);
21357        return true;
21358    }
21359
21360    /**
21361     * Modifies the input matrix such that it maps view-local coordinates to
21362     * on-screen coordinates.
21363     *
21364     * @param m input matrix to modify
21365     * @hide
21366     */
21367    public void transformMatrixToGlobal(Matrix m) {
21368        final ViewParent parent = mParent;
21369        if (parent instanceof View) {
21370            final View vp = (View) parent;
21371            vp.transformMatrixToGlobal(m);
21372            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
21373        } else if (parent instanceof ViewRootImpl) {
21374            final ViewRootImpl vr = (ViewRootImpl) parent;
21375            vr.transformMatrixToGlobal(m);
21376            m.preTranslate(0, -vr.mCurScrollY);
21377        }
21378
21379        m.preTranslate(mLeft, mTop);
21380
21381        if (!hasIdentityMatrix()) {
21382            m.preConcat(getMatrix());
21383        }
21384    }
21385
21386    /**
21387     * Modifies the input matrix such that it maps on-screen coordinates to
21388     * view-local coordinates.
21389     *
21390     * @param m input matrix to modify
21391     * @hide
21392     */
21393    public void transformMatrixToLocal(Matrix m) {
21394        final ViewParent parent = mParent;
21395        if (parent instanceof View) {
21396            final View vp = (View) parent;
21397            vp.transformMatrixToLocal(m);
21398            m.postTranslate(vp.mScrollX, vp.mScrollY);
21399        } else if (parent instanceof ViewRootImpl) {
21400            final ViewRootImpl vr = (ViewRootImpl) parent;
21401            vr.transformMatrixToLocal(m);
21402            m.postTranslate(0, vr.mCurScrollY);
21403        }
21404
21405        m.postTranslate(-mLeft, -mTop);
21406
21407        if (!hasIdentityMatrix()) {
21408            m.postConcat(getInverseMatrix());
21409        }
21410    }
21411
21412    /**
21413     * @hide
21414     */
21415    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
21416            @ViewDebug.IntToString(from = 0, to = "x"),
21417            @ViewDebug.IntToString(from = 1, to = "y")
21418    })
21419    public int[] getLocationOnScreen() {
21420        int[] location = new int[2];
21421        getLocationOnScreen(location);
21422        return location;
21423    }
21424
21425    /**
21426     * <p>Computes the coordinates of this view on the screen. The argument
21427     * must be an array of two integers. After the method returns, the array
21428     * contains the x and y location in that order.</p>
21429     *
21430     * @param outLocation an array of two integers in which to hold the coordinates
21431     */
21432    public void getLocationOnScreen(@Size(2) int[] outLocation) {
21433        getLocationInWindow(outLocation);
21434
21435        final AttachInfo info = mAttachInfo;
21436        if (info != null) {
21437            outLocation[0] += info.mWindowLeft;
21438            outLocation[1] += info.mWindowTop;
21439        }
21440    }
21441
21442    /**
21443     * <p>Computes the coordinates of this view in its window. The argument
21444     * must be an array of two integers. After the method returns, the array
21445     * contains the x and y location in that order.</p>
21446     *
21447     * @param outLocation an array of two integers in which to hold the coordinates
21448     */
21449    public void getLocationInWindow(@Size(2) int[] outLocation) {
21450        if (outLocation == null || outLocation.length < 2) {
21451            throw new IllegalArgumentException("outLocation must be an array of two integers");
21452        }
21453
21454        outLocation[0] = 0;
21455        outLocation[1] = 0;
21456
21457        transformFromViewToWindowSpace(outLocation);
21458    }
21459
21460    /** @hide */
21461    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
21462        if (inOutLocation == null || inOutLocation.length < 2) {
21463            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
21464        }
21465
21466        if (mAttachInfo == null) {
21467            // When the view is not attached to a window, this method does not make sense
21468            inOutLocation[0] = inOutLocation[1] = 0;
21469            return;
21470        }
21471
21472        float position[] = mAttachInfo.mTmpTransformLocation;
21473        position[0] = inOutLocation[0];
21474        position[1] = inOutLocation[1];
21475
21476        if (!hasIdentityMatrix()) {
21477            getMatrix().mapPoints(position);
21478        }
21479
21480        position[0] += mLeft;
21481        position[1] += mTop;
21482
21483        ViewParent viewParent = mParent;
21484        while (viewParent instanceof View) {
21485            final View view = (View) viewParent;
21486
21487            position[0] -= view.mScrollX;
21488            position[1] -= view.mScrollY;
21489
21490            if (!view.hasIdentityMatrix()) {
21491                view.getMatrix().mapPoints(position);
21492            }
21493
21494            position[0] += view.mLeft;
21495            position[1] += view.mTop;
21496
21497            viewParent = view.mParent;
21498         }
21499
21500        if (viewParent instanceof ViewRootImpl) {
21501            // *cough*
21502            final ViewRootImpl vr = (ViewRootImpl) viewParent;
21503            position[1] -= vr.mCurScrollY;
21504        }
21505
21506        inOutLocation[0] = Math.round(position[0]);
21507        inOutLocation[1] = Math.round(position[1]);
21508    }
21509
21510    /**
21511     * @param id the id of the view to be found
21512     * @return the view of the specified id, null if cannot be found
21513     * @hide
21514     */
21515    protected <T extends View> T findViewTraversal(@IdRes int id) {
21516        if (id == mID) {
21517            return (T) this;
21518        }
21519        return null;
21520    }
21521
21522    /**
21523     * @param tag the tag of the view to be found
21524     * @return the view of specified tag, null if cannot be found
21525     * @hide
21526     */
21527    protected <T extends View> T findViewWithTagTraversal(Object tag) {
21528        if (tag != null && tag.equals(mTag)) {
21529            return (T) this;
21530        }
21531        return null;
21532    }
21533
21534    /**
21535     * @param predicate The predicate to evaluate.
21536     * @param childToSkip If not null, ignores this child during the recursive traversal.
21537     * @return The first view that matches the predicate or null.
21538     * @hide
21539     */
21540    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
21541            View childToSkip) {
21542        if (predicate.test(this)) {
21543            return (T) this;
21544        }
21545        return null;
21546    }
21547
21548    /**
21549     * Finds the first descendant view with the given ID, the view itself if
21550     * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
21551     * (< 0) or there is no matching view in the hierarchy.
21552     * <p>
21553     * <strong>Note:</strong> In most cases -- depending on compiler support --
21554     * the resulting view is automatically cast to the target class type. If
21555     * the target class type is unconstrained, an explicit cast may be
21556     * necessary.
21557     *
21558     * @param id the ID to search for
21559     * @return a view with given ID if found, or {@code null} otherwise
21560     * @see View#findViewById(int)
21561     */
21562    @Nullable
21563    public final <T extends View> T findViewById(@IdRes int id) {
21564        if (id == NO_ID) {
21565            return null;
21566        }
21567        return findViewTraversal(id);
21568    }
21569
21570    /**
21571     * Finds a view by its unuque and stable accessibility id.
21572     *
21573     * @param accessibilityId The searched accessibility id.
21574     * @return The found view.
21575     */
21576    final <T extends View> T findViewByAccessibilityId(int accessibilityId) {
21577        if (accessibilityId < 0) {
21578            return null;
21579        }
21580        T view = findViewByAccessibilityIdTraversal(accessibilityId);
21581        if (view != null) {
21582            return view.includeForAccessibility() ? view : null;
21583        }
21584        return null;
21585    }
21586
21587    /**
21588     * Performs the traversal to find a view by its unique and stable accessibility id.
21589     *
21590     * <strong>Note:</strong>This method does not stop at the root namespace
21591     * boundary since the user can touch the screen at an arbitrary location
21592     * potentially crossing the root namespace boundary which will send an
21593     * accessibility event to accessibility services and they should be able
21594     * to obtain the event source. Also accessibility ids are guaranteed to be
21595     * unique in the window.
21596     *
21597     * @param accessibilityId The accessibility id.
21598     * @return The found view.
21599     * @hide
21600     */
21601    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
21602        if (getAccessibilityViewId() == accessibilityId) {
21603            return (T) this;
21604        }
21605        return null;
21606    }
21607
21608    /**
21609     * Performs the traversal to find a view by its autofill id.
21610     *
21611     * <strong>Note:</strong>This method does not stop at the root namespace
21612     * boundary.
21613     *
21614     * @param autofillId The autofill id.
21615     * @return The found view.
21616     * @hide
21617     */
21618    public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
21619        if (getAutofillViewId() == autofillId) {
21620            return (T) this;
21621        }
21622        return null;
21623    }
21624
21625    /**
21626     * Look for a child view with the given tag.  If this view has the given
21627     * tag, return this view.
21628     *
21629     * @param tag The tag to search for, using "tag.equals(getTag())".
21630     * @return The View that has the given tag in the hierarchy or null
21631     */
21632    public final <T extends View> T findViewWithTag(Object tag) {
21633        if (tag == null) {
21634            return null;
21635        }
21636        return findViewWithTagTraversal(tag);
21637    }
21638
21639    /**
21640     * Look for a child view that matches the specified predicate.
21641     * If this view matches the predicate, return this view.
21642     *
21643     * @param predicate The predicate to evaluate.
21644     * @return The first view that matches the predicate or null.
21645     * @hide
21646     */
21647    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
21648        return findViewByPredicateTraversal(predicate, null);
21649    }
21650
21651    /**
21652     * Look for a child view that matches the specified predicate,
21653     * starting with the specified view and its descendents and then
21654     * recusively searching the ancestors and siblings of that view
21655     * until this view is reached.
21656     *
21657     * This method is useful in cases where the predicate does not match
21658     * a single unique view (perhaps multiple views use the same id)
21659     * and we are trying to find the view that is "closest" in scope to the
21660     * starting view.
21661     *
21662     * @param start The view to start from.
21663     * @param predicate The predicate to evaluate.
21664     * @return The first view that matches the predicate or null.
21665     * @hide
21666     */
21667    public final <T extends View> T findViewByPredicateInsideOut(
21668            View start, Predicate<View> predicate) {
21669        View childToSkip = null;
21670        for (;;) {
21671            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
21672            if (view != null || start == this) {
21673                return view;
21674            }
21675
21676            ViewParent parent = start.getParent();
21677            if (parent == null || !(parent instanceof View)) {
21678                return null;
21679            }
21680
21681            childToSkip = start;
21682            start = (View) parent;
21683        }
21684    }
21685
21686    /**
21687     * Sets the identifier for this view. The identifier does not have to be
21688     * unique in this view's hierarchy. The identifier should be a positive
21689     * number.
21690     *
21691     * @see #NO_ID
21692     * @see #getId()
21693     * @see #findViewById(int)
21694     *
21695     * @param id a number used to identify the view
21696     *
21697     * @attr ref android.R.styleable#View_id
21698     */
21699    public void setId(@IdRes int id) {
21700        mID = id;
21701        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
21702            mID = generateViewId();
21703        }
21704    }
21705
21706    /**
21707     * {@hide}
21708     *
21709     * @param isRoot true if the view belongs to the root namespace, false
21710     *        otherwise
21711     */
21712    public void setIsRootNamespace(boolean isRoot) {
21713        if (isRoot) {
21714            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
21715        } else {
21716            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
21717        }
21718    }
21719
21720    /**
21721     * {@hide}
21722     *
21723     * @return true if the view belongs to the root namespace, false otherwise
21724     */
21725    public boolean isRootNamespace() {
21726        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
21727    }
21728
21729    /**
21730     * Returns this view's identifier.
21731     *
21732     * @return a positive integer used to identify the view or {@link #NO_ID}
21733     *         if the view has no ID
21734     *
21735     * @see #setId(int)
21736     * @see #findViewById(int)
21737     * @attr ref android.R.styleable#View_id
21738     */
21739    @IdRes
21740    @ViewDebug.CapturedViewProperty
21741    public int getId() {
21742        return mID;
21743    }
21744
21745    /**
21746     * Returns this view's tag.
21747     *
21748     * @return the Object stored in this view as a tag, or {@code null} if not
21749     *         set
21750     *
21751     * @see #setTag(Object)
21752     * @see #getTag(int)
21753     */
21754    @ViewDebug.ExportedProperty
21755    public Object getTag() {
21756        return mTag;
21757    }
21758
21759    /**
21760     * Sets the tag associated with this view. A tag can be used to mark
21761     * a view in its hierarchy and does not have to be unique within the
21762     * hierarchy. Tags can also be used to store data within a view without
21763     * resorting to another data structure.
21764     *
21765     * @param tag an Object to tag the view with
21766     *
21767     * @see #getTag()
21768     * @see #setTag(int, Object)
21769     */
21770    public void setTag(final Object tag) {
21771        mTag = tag;
21772    }
21773
21774    /**
21775     * Returns the tag associated with this view and the specified key.
21776     *
21777     * @param key The key identifying the tag
21778     *
21779     * @return the Object stored in this view as a tag, or {@code null} if not
21780     *         set
21781     *
21782     * @see #setTag(int, Object)
21783     * @see #getTag()
21784     */
21785    public Object getTag(int key) {
21786        if (mKeyedTags != null) return mKeyedTags.get(key);
21787        return null;
21788    }
21789
21790    /**
21791     * Sets a tag associated with this view and a key. A tag can be used
21792     * to mark a view in its hierarchy and does not have to be unique within
21793     * the hierarchy. Tags can also be used to store data within a view
21794     * without resorting to another data structure.
21795     *
21796     * The specified key should be an id declared in the resources of the
21797     * application to ensure it is unique (see the <a
21798     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21799     * Keys identified as belonging to
21800     * the Android framework or not associated with any package will cause
21801     * an {@link IllegalArgumentException} to be thrown.
21802     *
21803     * @param key The key identifying the tag
21804     * @param tag An Object to tag the view with
21805     *
21806     * @throws IllegalArgumentException If they specified key is not valid
21807     *
21808     * @see #setTag(Object)
21809     * @see #getTag(int)
21810     */
21811    public void setTag(int key, final Object tag) {
21812        // If the package id is 0x00 or 0x01, it's either an undefined package
21813        // or a framework id
21814        if ((key >>> 24) < 2) {
21815            throw new IllegalArgumentException("The key must be an application-specific "
21816                    + "resource id.");
21817        }
21818
21819        setKeyedTag(key, tag);
21820    }
21821
21822    /**
21823     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21824     * framework id.
21825     *
21826     * @hide
21827     */
21828    public void setTagInternal(int key, Object tag) {
21829        if ((key >>> 24) != 0x1) {
21830            throw new IllegalArgumentException("The key must be a framework-specific "
21831                    + "resource id.");
21832        }
21833
21834        setKeyedTag(key, tag);
21835    }
21836
21837    private void setKeyedTag(int key, Object tag) {
21838        if (mKeyedTags == null) {
21839            mKeyedTags = new SparseArray<Object>(2);
21840        }
21841
21842        mKeyedTags.put(key, tag);
21843    }
21844
21845    /**
21846     * Prints information about this view in the log output, with the tag
21847     * {@link #VIEW_LOG_TAG}.
21848     *
21849     * @hide
21850     */
21851    public void debug() {
21852        debug(0);
21853    }
21854
21855    /**
21856     * Prints information about this view in the log output, with the tag
21857     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21858     * indentation defined by the <code>depth</code>.
21859     *
21860     * @param depth the indentation level
21861     *
21862     * @hide
21863     */
21864    protected void debug(int depth) {
21865        String output = debugIndent(depth - 1);
21866
21867        output += "+ " + this;
21868        int id = getId();
21869        if (id != -1) {
21870            output += " (id=" + id + ")";
21871        }
21872        Object tag = getTag();
21873        if (tag != null) {
21874            output += " (tag=" + tag + ")";
21875        }
21876        Log.d(VIEW_LOG_TAG, output);
21877
21878        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21879            output = debugIndent(depth) + " FOCUSED";
21880            Log.d(VIEW_LOG_TAG, output);
21881        }
21882
21883        output = debugIndent(depth);
21884        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21885                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21886                + "} ";
21887        Log.d(VIEW_LOG_TAG, output);
21888
21889        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21890                || mPaddingBottom != 0) {
21891            output = debugIndent(depth);
21892            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21893                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21894            Log.d(VIEW_LOG_TAG, output);
21895        }
21896
21897        output = debugIndent(depth);
21898        output += "mMeasureWidth=" + mMeasuredWidth +
21899                " mMeasureHeight=" + mMeasuredHeight;
21900        Log.d(VIEW_LOG_TAG, output);
21901
21902        output = debugIndent(depth);
21903        if (mLayoutParams == null) {
21904            output += "BAD! no layout params";
21905        } else {
21906            output = mLayoutParams.debug(output);
21907        }
21908        Log.d(VIEW_LOG_TAG, output);
21909
21910        output = debugIndent(depth);
21911        output += "flags={";
21912        output += View.printFlags(mViewFlags);
21913        output += "}";
21914        Log.d(VIEW_LOG_TAG, output);
21915
21916        output = debugIndent(depth);
21917        output += "privateFlags={";
21918        output += View.printPrivateFlags(mPrivateFlags);
21919        output += "}";
21920        Log.d(VIEW_LOG_TAG, output);
21921    }
21922
21923    /**
21924     * Creates a string of whitespaces used for indentation.
21925     *
21926     * @param depth the indentation level
21927     * @return a String containing (depth * 2 + 3) * 2 white spaces
21928     *
21929     * @hide
21930     */
21931    protected static String debugIndent(int depth) {
21932        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21933        for (int i = 0; i < (depth * 2) + 3; i++) {
21934            spaces.append(' ').append(' ');
21935        }
21936        return spaces.toString();
21937    }
21938
21939    /**
21940     * <p>Return the offset of the widget's text baseline from the widget's top
21941     * boundary. If this widget does not support baseline alignment, this
21942     * method returns -1. </p>
21943     *
21944     * @return the offset of the baseline within the widget's bounds or -1
21945     *         if baseline alignment is not supported
21946     */
21947    @ViewDebug.ExportedProperty(category = "layout")
21948    public int getBaseline() {
21949        return -1;
21950    }
21951
21952    /**
21953     * Returns whether the view hierarchy is currently undergoing a layout pass. This
21954     * information is useful to avoid situations such as calling {@link #requestLayout()} during
21955     * a layout pass.
21956     *
21957     * @return whether the view hierarchy is currently undergoing a layout pass
21958     */
21959    public boolean isInLayout() {
21960        ViewRootImpl viewRoot = getViewRootImpl();
21961        return (viewRoot != null && viewRoot.isInLayout());
21962    }
21963
21964    /**
21965     * Call this when something has changed which has invalidated the
21966     * layout of this view. This will schedule a layout pass of the view
21967     * tree. This should not be called while the view hierarchy is currently in a layout
21968     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21969     * end of the current layout pass (and then layout will run again) or after the current
21970     * frame is drawn and the next layout occurs.
21971     *
21972     * <p>Subclasses which override this method should call the superclass method to
21973     * handle possible request-during-layout errors correctly.</p>
21974     */
21975    @CallSuper
21976    public void requestLayout() {
21977        if (mMeasureCache != null) mMeasureCache.clear();
21978
21979        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21980            // Only trigger request-during-layout logic if this is the view requesting it,
21981            // not the views in its parent hierarchy
21982            ViewRootImpl viewRoot = getViewRootImpl();
21983            if (viewRoot != null && viewRoot.isInLayout()) {
21984                if (!viewRoot.requestLayoutDuringLayout(this)) {
21985                    return;
21986                }
21987            }
21988            mAttachInfo.mViewRequestingLayout = this;
21989        }
21990
21991        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21992        mPrivateFlags |= PFLAG_INVALIDATED;
21993
21994        if (mParent != null && !mParent.isLayoutRequested()) {
21995            mParent.requestLayout();
21996        }
21997        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21998            mAttachInfo.mViewRequestingLayout = null;
21999        }
22000    }
22001
22002    /**
22003     * Forces this view to be laid out during the next layout pass.
22004     * This method does not call requestLayout() or forceLayout()
22005     * on the parent.
22006     */
22007    public void forceLayout() {
22008        if (mMeasureCache != null) mMeasureCache.clear();
22009
22010        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
22011        mPrivateFlags |= PFLAG_INVALIDATED;
22012    }
22013
22014    /**
22015     * <p>
22016     * This is called to find out how big a view should be. The parent
22017     * supplies constraint information in the width and height parameters.
22018     * </p>
22019     *
22020     * <p>
22021     * The actual measurement work of a view is performed in
22022     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
22023     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
22024     * </p>
22025     *
22026     *
22027     * @param widthMeasureSpec Horizontal space requirements as imposed by the
22028     *        parent
22029     * @param heightMeasureSpec Vertical space requirements as imposed by the
22030     *        parent
22031     *
22032     * @see #onMeasure(int, int)
22033     */
22034    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
22035        boolean optical = isLayoutModeOptical(this);
22036        if (optical != isLayoutModeOptical(mParent)) {
22037            Insets insets = getOpticalInsets();
22038            int oWidth  = insets.left + insets.right;
22039            int oHeight = insets.top  + insets.bottom;
22040            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
22041            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
22042        }
22043
22044        // Suppress sign extension for the low bytes
22045        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
22046        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
22047
22048        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
22049
22050        // Optimize layout by avoiding an extra EXACTLY pass when the view is
22051        // already measured as the correct size. In API 23 and below, this
22052        // extra pass is required to make LinearLayout re-distribute weight.
22053        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
22054                || heightMeasureSpec != mOldHeightMeasureSpec;
22055        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
22056                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
22057        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
22058                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
22059        final boolean needsLayout = specChanged
22060                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
22061
22062        if (forceLayout || needsLayout) {
22063            // first clears the measured dimension flag
22064            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
22065
22066            resolveRtlPropertiesIfNeeded();
22067
22068            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
22069            if (cacheIndex < 0 || sIgnoreMeasureCache) {
22070                // measure ourselves, this should set the measured dimension flag back
22071                onMeasure(widthMeasureSpec, heightMeasureSpec);
22072                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
22073            } else {
22074                long value = mMeasureCache.valueAt(cacheIndex);
22075                // Casting a long to int drops the high 32 bits, no mask needed
22076                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
22077                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
22078            }
22079
22080            // flag not set, setMeasuredDimension() was not invoked, we raise
22081            // an exception to warn the developer
22082            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
22083                throw new IllegalStateException("View with id " + getId() + ": "
22084                        + getClass().getName() + "#onMeasure() did not set the"
22085                        + " measured dimension by calling"
22086                        + " setMeasuredDimension()");
22087            }
22088
22089            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
22090        }
22091
22092        mOldWidthMeasureSpec = widthMeasureSpec;
22093        mOldHeightMeasureSpec = heightMeasureSpec;
22094
22095        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
22096                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
22097    }
22098
22099    /**
22100     * <p>
22101     * Measure the view and its content to determine the measured width and the
22102     * measured height. This method is invoked by {@link #measure(int, int)} and
22103     * should be overridden by subclasses to provide accurate and efficient
22104     * measurement of their contents.
22105     * </p>
22106     *
22107     * <p>
22108     * <strong>CONTRACT:</strong> When overriding this method, you
22109     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
22110     * measured width and height of this view. Failure to do so will trigger an
22111     * <code>IllegalStateException</code>, thrown by
22112     * {@link #measure(int, int)}. Calling the superclass'
22113     * {@link #onMeasure(int, int)} is a valid use.
22114     * </p>
22115     *
22116     * <p>
22117     * The base class implementation of measure defaults to the background size,
22118     * unless a larger size is allowed by the MeasureSpec. Subclasses should
22119     * override {@link #onMeasure(int, int)} to provide better measurements of
22120     * their content.
22121     * </p>
22122     *
22123     * <p>
22124     * If this method is overridden, it is the subclass's responsibility to make
22125     * sure the measured height and width are at least the view's minimum height
22126     * and width ({@link #getSuggestedMinimumHeight()} and
22127     * {@link #getSuggestedMinimumWidth()}).
22128     * </p>
22129     *
22130     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
22131     *                         The requirements are encoded with
22132     *                         {@link android.view.View.MeasureSpec}.
22133     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
22134     *                         The requirements are encoded with
22135     *                         {@link android.view.View.MeasureSpec}.
22136     *
22137     * @see #getMeasuredWidth()
22138     * @see #getMeasuredHeight()
22139     * @see #setMeasuredDimension(int, int)
22140     * @see #getSuggestedMinimumHeight()
22141     * @see #getSuggestedMinimumWidth()
22142     * @see android.view.View.MeasureSpec#getMode(int)
22143     * @see android.view.View.MeasureSpec#getSize(int)
22144     */
22145    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
22146        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
22147                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
22148    }
22149
22150    /**
22151     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
22152     * measured width and measured height. Failing to do so will trigger an
22153     * exception at measurement time.</p>
22154     *
22155     * @param measuredWidth The measured width of this view.  May be a complex
22156     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22157     * {@link #MEASURED_STATE_TOO_SMALL}.
22158     * @param measuredHeight The measured height of this view.  May be a complex
22159     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22160     * {@link #MEASURED_STATE_TOO_SMALL}.
22161     */
22162    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
22163        boolean optical = isLayoutModeOptical(this);
22164        if (optical != isLayoutModeOptical(mParent)) {
22165            Insets insets = getOpticalInsets();
22166            int opticalWidth  = insets.left + insets.right;
22167            int opticalHeight = insets.top  + insets.bottom;
22168
22169            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
22170            measuredHeight += optical ? opticalHeight : -opticalHeight;
22171        }
22172        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
22173    }
22174
22175    /**
22176     * Sets the measured dimension without extra processing for things like optical bounds.
22177     * Useful for reapplying consistent values that have already been cooked with adjustments
22178     * for optical bounds, etc. such as those from the measurement cache.
22179     *
22180     * @param measuredWidth The measured width of this view.  May be a complex
22181     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22182     * {@link #MEASURED_STATE_TOO_SMALL}.
22183     * @param measuredHeight The measured height of this view.  May be a complex
22184     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22185     * {@link #MEASURED_STATE_TOO_SMALL}.
22186     */
22187    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
22188        mMeasuredWidth = measuredWidth;
22189        mMeasuredHeight = measuredHeight;
22190
22191        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
22192    }
22193
22194    /**
22195     * Merge two states as returned by {@link #getMeasuredState()}.
22196     * @param curState The current state as returned from a view or the result
22197     * of combining multiple views.
22198     * @param newState The new view state to combine.
22199     * @return Returns a new integer reflecting the combination of the two
22200     * states.
22201     */
22202    public static int combineMeasuredStates(int curState, int newState) {
22203        return curState | newState;
22204    }
22205
22206    /**
22207     * Version of {@link #resolveSizeAndState(int, int, int)}
22208     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
22209     */
22210    public static int resolveSize(int size, int measureSpec) {
22211        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
22212    }
22213
22214    /**
22215     * Utility to reconcile a desired size and state, with constraints imposed
22216     * by a MeasureSpec. Will take the desired size, unless a different size
22217     * is imposed by the constraints. The returned value is a compound integer,
22218     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
22219     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
22220     * resulting size is smaller than the size the view wants to be.
22221     *
22222     * @param size How big the view wants to be.
22223     * @param measureSpec Constraints imposed by the parent.
22224     * @param childMeasuredState Size information bit mask for the view's
22225     *                           children.
22226     * @return Size information bit mask as defined by
22227     *         {@link #MEASURED_SIZE_MASK} and
22228     *         {@link #MEASURED_STATE_TOO_SMALL}.
22229     */
22230    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
22231        final int specMode = MeasureSpec.getMode(measureSpec);
22232        final int specSize = MeasureSpec.getSize(measureSpec);
22233        final int result;
22234        switch (specMode) {
22235            case MeasureSpec.AT_MOST:
22236                if (specSize < size) {
22237                    result = specSize | MEASURED_STATE_TOO_SMALL;
22238                } else {
22239                    result = size;
22240                }
22241                break;
22242            case MeasureSpec.EXACTLY:
22243                result = specSize;
22244                break;
22245            case MeasureSpec.UNSPECIFIED:
22246            default:
22247                result = size;
22248        }
22249        return result | (childMeasuredState & MEASURED_STATE_MASK);
22250    }
22251
22252    /**
22253     * Utility to return a default size. Uses the supplied size if the
22254     * MeasureSpec imposed no constraints. Will get larger if allowed
22255     * by the MeasureSpec.
22256     *
22257     * @param size Default size for this view
22258     * @param measureSpec Constraints imposed by the parent
22259     * @return The size this view should be.
22260     */
22261    public static int getDefaultSize(int size, int measureSpec) {
22262        int result = size;
22263        int specMode = MeasureSpec.getMode(measureSpec);
22264        int specSize = MeasureSpec.getSize(measureSpec);
22265
22266        switch (specMode) {
22267        case MeasureSpec.UNSPECIFIED:
22268            result = size;
22269            break;
22270        case MeasureSpec.AT_MOST:
22271        case MeasureSpec.EXACTLY:
22272            result = specSize;
22273            break;
22274        }
22275        return result;
22276    }
22277
22278    /**
22279     * Returns the suggested minimum height that the view should use. This
22280     * returns the maximum of the view's minimum height
22281     * and the background's minimum height
22282     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
22283     * <p>
22284     * When being used in {@link #onMeasure(int, int)}, the caller should still
22285     * ensure the returned height is within the requirements of the parent.
22286     *
22287     * @return The suggested minimum height of the view.
22288     */
22289    protected int getSuggestedMinimumHeight() {
22290        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
22291
22292    }
22293
22294    /**
22295     * Returns the suggested minimum width that the view should use. This
22296     * returns the maximum of the view's minimum width
22297     * and the background's minimum width
22298     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
22299     * <p>
22300     * When being used in {@link #onMeasure(int, int)}, the caller should still
22301     * ensure the returned width is within the requirements of the parent.
22302     *
22303     * @return The suggested minimum width of the view.
22304     */
22305    protected int getSuggestedMinimumWidth() {
22306        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
22307    }
22308
22309    /**
22310     * Returns the minimum height of the view.
22311     *
22312     * @return the minimum height the view will try to be, in pixels
22313     *
22314     * @see #setMinimumHeight(int)
22315     *
22316     * @attr ref android.R.styleable#View_minHeight
22317     */
22318    public int getMinimumHeight() {
22319        return mMinHeight;
22320    }
22321
22322    /**
22323     * Sets the minimum height of the view. It is not guaranteed the view will
22324     * be able to achieve this minimum height (for example, if its parent layout
22325     * constrains it with less available height).
22326     *
22327     * @param minHeight The minimum height the view will try to be, in pixels
22328     *
22329     * @see #getMinimumHeight()
22330     *
22331     * @attr ref android.R.styleable#View_minHeight
22332     */
22333    @RemotableViewMethod
22334    public void setMinimumHeight(int minHeight) {
22335        mMinHeight = minHeight;
22336        requestLayout();
22337    }
22338
22339    /**
22340     * Returns the minimum width of the view.
22341     *
22342     * @return the minimum width the view will try to be, in pixels
22343     *
22344     * @see #setMinimumWidth(int)
22345     *
22346     * @attr ref android.R.styleable#View_minWidth
22347     */
22348    public int getMinimumWidth() {
22349        return mMinWidth;
22350    }
22351
22352    /**
22353     * Sets the minimum width of the view. It is not guaranteed the view will
22354     * be able to achieve this minimum width (for example, if its parent layout
22355     * constrains it with less available width).
22356     *
22357     * @param minWidth The minimum width the view will try to be, in pixels
22358     *
22359     * @see #getMinimumWidth()
22360     *
22361     * @attr ref android.R.styleable#View_minWidth
22362     */
22363    public void setMinimumWidth(int minWidth) {
22364        mMinWidth = minWidth;
22365        requestLayout();
22366
22367    }
22368
22369    /**
22370     * Get the animation currently associated with this view.
22371     *
22372     * @return The animation that is currently playing or
22373     *         scheduled to play for this view.
22374     */
22375    public Animation getAnimation() {
22376        return mCurrentAnimation;
22377    }
22378
22379    /**
22380     * Start the specified animation now.
22381     *
22382     * @param animation the animation to start now
22383     */
22384    public void startAnimation(Animation animation) {
22385        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
22386        setAnimation(animation);
22387        invalidateParentCaches();
22388        invalidate(true);
22389    }
22390
22391    /**
22392     * Cancels any animations for this view.
22393     */
22394    public void clearAnimation() {
22395        if (mCurrentAnimation != null) {
22396            mCurrentAnimation.detach();
22397        }
22398        mCurrentAnimation = null;
22399        invalidateParentIfNeeded();
22400    }
22401
22402    /**
22403     * Sets the next animation to play for this view.
22404     * If you want the animation to play immediately, use
22405     * {@link #startAnimation(android.view.animation.Animation)} instead.
22406     * This method provides allows fine-grained
22407     * control over the start time and invalidation, but you
22408     * must make sure that 1) the animation has a start time set, and
22409     * 2) the view's parent (which controls animations on its children)
22410     * will be invalidated when the animation is supposed to
22411     * start.
22412     *
22413     * @param animation The next animation, or null.
22414     */
22415    public void setAnimation(Animation animation) {
22416        mCurrentAnimation = animation;
22417
22418        if (animation != null) {
22419            // If the screen is off assume the animation start time is now instead of
22420            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
22421            // would cause the animation to start when the screen turns back on
22422            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
22423                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
22424                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
22425            }
22426            animation.reset();
22427        }
22428    }
22429
22430    /**
22431     * Invoked by a parent ViewGroup to notify the start of the animation
22432     * currently associated with this view. If you override this method,
22433     * always call super.onAnimationStart();
22434     *
22435     * @see #setAnimation(android.view.animation.Animation)
22436     * @see #getAnimation()
22437     */
22438    @CallSuper
22439    protected void onAnimationStart() {
22440        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
22441    }
22442
22443    /**
22444     * Invoked by a parent ViewGroup to notify the end of the animation
22445     * currently associated with this view. If you override this method,
22446     * always call super.onAnimationEnd();
22447     *
22448     * @see #setAnimation(android.view.animation.Animation)
22449     * @see #getAnimation()
22450     */
22451    @CallSuper
22452    protected void onAnimationEnd() {
22453        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
22454    }
22455
22456    /**
22457     * Invoked if there is a Transform that involves alpha. Subclass that can
22458     * draw themselves with the specified alpha should return true, and then
22459     * respect that alpha when their onDraw() is called. If this returns false
22460     * then the view may be redirected to draw into an offscreen buffer to
22461     * fulfill the request, which will look fine, but may be slower than if the
22462     * subclass handles it internally. The default implementation returns false.
22463     *
22464     * @param alpha The alpha (0..255) to apply to the view's drawing
22465     * @return true if the view can draw with the specified alpha.
22466     */
22467    protected boolean onSetAlpha(int alpha) {
22468        return false;
22469    }
22470
22471    /**
22472     * This is used by the RootView to perform an optimization when
22473     * the view hierarchy contains one or several SurfaceView.
22474     * SurfaceView is always considered transparent, but its children are not,
22475     * therefore all View objects remove themselves from the global transparent
22476     * region (passed as a parameter to this function).
22477     *
22478     * @param region The transparent region for this ViewAncestor (window).
22479     *
22480     * @return Returns true if the effective visibility of the view at this
22481     * point is opaque, regardless of the transparent region; returns false
22482     * if it is possible for underlying windows to be seen behind the view.
22483     *
22484     * {@hide}
22485     */
22486    public boolean gatherTransparentRegion(Region region) {
22487        final AttachInfo attachInfo = mAttachInfo;
22488        if (region != null && attachInfo != null) {
22489            final int pflags = mPrivateFlags;
22490            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
22491                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
22492                // remove it from the transparent region.
22493                final int[] location = attachInfo.mTransparentLocation;
22494                getLocationInWindow(location);
22495                // When a view has Z value, then it will be better to leave some area below the view
22496                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
22497                // the bottom part needs more offset than the left, top and right parts due to the
22498                // spot light effects.
22499                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
22500                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
22501                        location[0] + mRight - mLeft + shadowOffset,
22502                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
22503            } else {
22504                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
22505                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
22506                    // the background drawable's non-transparent parts from this transparent region.
22507                    applyDrawableToTransparentRegion(mBackground, region);
22508                }
22509                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
22510                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
22511                    // Similarly, we remove the foreground drawable's non-transparent parts.
22512                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
22513                }
22514                if (mDefaultFocusHighlight != null
22515                        && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
22516                    // Similarly, we remove the default focus highlight's non-transparent parts.
22517                    applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
22518                }
22519            }
22520        }
22521        return true;
22522    }
22523
22524    /**
22525     * Play a sound effect for this view.
22526     *
22527     * <p>The framework will play sound effects for some built in actions, such as
22528     * clicking, but you may wish to play these effects in your widget,
22529     * for instance, for internal navigation.
22530     *
22531     * <p>The sound effect will only be played if sound effects are enabled by the user, and
22532     * {@link #isSoundEffectsEnabled()} is true.
22533     *
22534     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
22535     */
22536    public void playSoundEffect(int soundConstant) {
22537        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
22538            return;
22539        }
22540        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
22541    }
22542
22543    /**
22544     * BZZZTT!!1!
22545     *
22546     * <p>Provide haptic feedback to the user for this view.
22547     *
22548     * <p>The framework will provide haptic feedback for some built in actions,
22549     * such as long presses, but you may wish to provide feedback for your
22550     * own widget.
22551     *
22552     * <p>The feedback will only be performed if
22553     * {@link #isHapticFeedbackEnabled()} is true.
22554     *
22555     * @param feedbackConstant One of the constants defined in
22556     * {@link HapticFeedbackConstants}
22557     */
22558    public boolean performHapticFeedback(int feedbackConstant) {
22559        return performHapticFeedback(feedbackConstant, 0);
22560    }
22561
22562    /**
22563     * BZZZTT!!1!
22564     *
22565     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
22566     *
22567     * @param feedbackConstant One of the constants defined in
22568     * {@link HapticFeedbackConstants}
22569     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
22570     */
22571    public boolean performHapticFeedback(int feedbackConstant, int flags) {
22572        if (mAttachInfo == null) {
22573            return false;
22574        }
22575        //noinspection SimplifiableIfStatement
22576        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
22577                && !isHapticFeedbackEnabled()) {
22578            return false;
22579        }
22580        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
22581                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
22582    }
22583
22584    /**
22585     * Request that the visibility of the status bar or other screen/window
22586     * decorations be changed.
22587     *
22588     * <p>This method is used to put the over device UI into temporary modes
22589     * where the user's attention is focused more on the application content,
22590     * by dimming or hiding surrounding system affordances.  This is typically
22591     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
22592     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
22593     * to be placed behind the action bar (and with these flags other system
22594     * affordances) so that smooth transitions between hiding and showing them
22595     * can be done.
22596     *
22597     * <p>Two representative examples of the use of system UI visibility is
22598     * implementing a content browsing application (like a magazine reader)
22599     * and a video playing application.
22600     *
22601     * <p>The first code shows a typical implementation of a View in a content
22602     * browsing application.  In this implementation, the application goes
22603     * into a content-oriented mode by hiding the status bar and action bar,
22604     * and putting the navigation elements into lights out mode.  The user can
22605     * then interact with content while in this mode.  Such an application should
22606     * provide an easy way for the user to toggle out of the mode (such as to
22607     * check information in the status bar or access notifications).  In the
22608     * implementation here, this is done simply by tapping on the content.
22609     *
22610     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
22611     *      content}
22612     *
22613     * <p>This second code sample shows a typical implementation of a View
22614     * in a video playing application.  In this situation, while the video is
22615     * playing the application would like to go into a complete full-screen mode,
22616     * to use as much of the display as possible for the video.  When in this state
22617     * the user can not interact with the application; the system intercepts
22618     * touching on the screen to pop the UI out of full screen mode.  See
22619     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
22620     *
22621     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
22622     *      content}
22623     *
22624     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22625     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22626     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22627     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22628     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22629     */
22630    public void setSystemUiVisibility(int visibility) {
22631        if (visibility != mSystemUiVisibility) {
22632            mSystemUiVisibility = visibility;
22633            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22634                mParent.recomputeViewAttributes(this);
22635            }
22636        }
22637    }
22638
22639    /**
22640     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
22641     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22642     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22643     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22644     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22645     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22646     */
22647    public int getSystemUiVisibility() {
22648        return mSystemUiVisibility;
22649    }
22650
22651    /**
22652     * Returns the current system UI visibility that is currently set for
22653     * the entire window.  This is the combination of the
22654     * {@link #setSystemUiVisibility(int)} values supplied by all of the
22655     * views in the window.
22656     */
22657    public int getWindowSystemUiVisibility() {
22658        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
22659    }
22660
22661    /**
22662     * Override to find out when the window's requested system UI visibility
22663     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
22664     * This is different from the callbacks received through
22665     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
22666     * in that this is only telling you about the local request of the window,
22667     * not the actual values applied by the system.
22668     */
22669    public void onWindowSystemUiVisibilityChanged(int visible) {
22670    }
22671
22672    /**
22673     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
22674     * the view hierarchy.
22675     */
22676    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
22677        onWindowSystemUiVisibilityChanged(visible);
22678    }
22679
22680    /**
22681     * Set a listener to receive callbacks when the visibility of the system bar changes.
22682     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
22683     */
22684    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
22685        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
22686        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22687            mParent.recomputeViewAttributes(this);
22688        }
22689    }
22690
22691    /**
22692     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
22693     * the view hierarchy.
22694     */
22695    public void dispatchSystemUiVisibilityChanged(int visibility) {
22696        ListenerInfo li = mListenerInfo;
22697        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
22698            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
22699                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
22700        }
22701    }
22702
22703    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
22704        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
22705        if (val != mSystemUiVisibility) {
22706            setSystemUiVisibility(val);
22707            return true;
22708        }
22709        return false;
22710    }
22711
22712    /** @hide */
22713    public void setDisabledSystemUiVisibility(int flags) {
22714        if (mAttachInfo != null) {
22715            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
22716                mAttachInfo.mDisabledSystemUiVisibility = flags;
22717                if (mParent != null) {
22718                    mParent.recomputeViewAttributes(this);
22719                }
22720            }
22721        }
22722    }
22723
22724    /**
22725     * Creates an image that the system displays during the drag and drop
22726     * operation. This is called a &quot;drag shadow&quot;. The default implementation
22727     * for a DragShadowBuilder based on a View returns an image that has exactly the same
22728     * appearance as the given View. The default also positions the center of the drag shadow
22729     * directly under the touch point. If no View is provided (the constructor with no parameters
22730     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
22731     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
22732     * default is an invisible drag shadow.
22733     * <p>
22734     * You are not required to use the View you provide to the constructor as the basis of the
22735     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
22736     * anything you want as the drag shadow.
22737     * </p>
22738     * <p>
22739     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
22740     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
22741     *  size and position of the drag shadow. It uses this data to construct a
22742     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
22743     *  so that your application can draw the shadow image in the Canvas.
22744     * </p>
22745     *
22746     * <div class="special reference">
22747     * <h3>Developer Guides</h3>
22748     * <p>For a guide to implementing drag and drop features, read the
22749     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22750     * </div>
22751     */
22752    public static class DragShadowBuilder {
22753        private final WeakReference<View> mView;
22754
22755        /**
22756         * Constructs a shadow image builder based on a View. By default, the resulting drag
22757         * shadow will have the same appearance and dimensions as the View, with the touch point
22758         * over the center of the View.
22759         * @param view A View. Any View in scope can be used.
22760         */
22761        public DragShadowBuilder(View view) {
22762            mView = new WeakReference<View>(view);
22763        }
22764
22765        /**
22766         * Construct a shadow builder object with no associated View.  This
22767         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
22768         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
22769         * to supply the drag shadow's dimensions and appearance without
22770         * reference to any View object. If they are not overridden, then the result is an
22771         * invisible drag shadow.
22772         */
22773        public DragShadowBuilder() {
22774            mView = new WeakReference<View>(null);
22775        }
22776
22777        /**
22778         * Returns the View object that had been passed to the
22779         * {@link #View.DragShadowBuilder(View)}
22780         * constructor.  If that View parameter was {@code null} or if the
22781         * {@link #View.DragShadowBuilder()}
22782         * constructor was used to instantiate the builder object, this method will return
22783         * null.
22784         *
22785         * @return The View object associate with this builder object.
22786         */
22787        @SuppressWarnings({"JavadocReference"})
22788        final public View getView() {
22789            return mView.get();
22790        }
22791
22792        /**
22793         * Provides the metrics for the shadow image. These include the dimensions of
22794         * the shadow image, and the point within that shadow that should
22795         * be centered under the touch location while dragging.
22796         * <p>
22797         * The default implementation sets the dimensions of the shadow to be the
22798         * same as the dimensions of the View itself and centers the shadow under
22799         * the touch point.
22800         * </p>
22801         *
22802         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22803         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22804         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22805         * image.
22806         *
22807         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22808         * shadow image that should be underneath the touch point during the drag and drop
22809         * operation. Your application must set {@link android.graphics.Point#x} to the
22810         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22811         */
22812        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22813            final View view = mView.get();
22814            if (view != null) {
22815                outShadowSize.set(view.getWidth(), view.getHeight());
22816                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22817            } else {
22818                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22819            }
22820        }
22821
22822        /**
22823         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22824         * based on the dimensions it received from the
22825         * {@link #onProvideShadowMetrics(Point, Point)} callback.
22826         *
22827         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22828         */
22829        public void onDrawShadow(Canvas canvas) {
22830            final View view = mView.get();
22831            if (view != null) {
22832                view.draw(canvas);
22833            } else {
22834                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22835            }
22836        }
22837    }
22838
22839    /**
22840     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22841     * startDragAndDrop()} for newer platform versions.
22842     */
22843    @Deprecated
22844    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22845                                   Object myLocalState, int flags) {
22846        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22847    }
22848
22849    /**
22850     * Starts a drag and drop operation. When your application calls this method, it passes a
22851     * {@link android.view.View.DragShadowBuilder} object to the system. The
22852     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22853     * to get metrics for the drag shadow, and then calls the object's
22854     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22855     * <p>
22856     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22857     *  drag events to all the View objects in your application that are currently visible. It does
22858     *  this either by calling the View object's drag listener (an implementation of
22859     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22860     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22861     *  Both are passed a {@link android.view.DragEvent} object that has a
22862     *  {@link android.view.DragEvent#getAction()} value of
22863     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22864     * </p>
22865     * <p>
22866     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22867     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22868     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22869     * to the View the user selected for dragging.
22870     * </p>
22871     * @param data A {@link android.content.ClipData} object pointing to the data to be
22872     * transferred by the drag and drop operation.
22873     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22874     * drag shadow.
22875     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22876     * drop operation. When dispatching drag events to views in the same activity this object
22877     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22878     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22879     * will return null).
22880     * <p>
22881     * myLocalState is a lightweight mechanism for the sending information from the dragged View
22882     * to the target Views. For example, it can contain flags that differentiate between a
22883     * a copy operation and a move operation.
22884     * </p>
22885     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22886     * flags, or any combination of the following:
22887     *     <ul>
22888     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22889     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22890     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22891     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22892     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22893     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22894     *     </ul>
22895     * @return {@code true} if the method completes successfully, or
22896     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22897     * do a drag, and so no drag operation is in progress.
22898     */
22899    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22900            Object myLocalState, int flags) {
22901        if (ViewDebug.DEBUG_DRAG) {
22902            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22903        }
22904        if (mAttachInfo == null) {
22905            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22906            return false;
22907        }
22908
22909        if (data != null) {
22910            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22911        }
22912
22913        boolean okay = false;
22914
22915        Point shadowSize = new Point();
22916        Point shadowTouchPoint = new Point();
22917        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22918
22919        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22920                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22921            throw new IllegalStateException("Drag shadow dimensions must not be negative");
22922        }
22923
22924        if (ViewDebug.DEBUG_DRAG) {
22925            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22926                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22927        }
22928        if (mAttachInfo.mDragSurface != null) {
22929            mAttachInfo.mDragSurface.release();
22930        }
22931        mAttachInfo.mDragSurface = new Surface();
22932        try {
22933            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22934                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22935            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22936                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22937            if (mAttachInfo.mDragToken != null) {
22938                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22939                try {
22940                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22941                    shadowBuilder.onDrawShadow(canvas);
22942                } finally {
22943                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22944                }
22945
22946                final ViewRootImpl root = getViewRootImpl();
22947
22948                // Cache the local state object for delivery with DragEvents
22949                root.setLocalDragState(myLocalState);
22950
22951                // repurpose 'shadowSize' for the last touch point
22952                root.getLastTouchPoint(shadowSize);
22953
22954                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22955                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22956                        shadowTouchPoint.x, shadowTouchPoint.y, data);
22957                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22958            }
22959        } catch (Exception e) {
22960            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22961            mAttachInfo.mDragSurface.destroy();
22962            mAttachInfo.mDragSurface = null;
22963        }
22964
22965        return okay;
22966    }
22967
22968    /**
22969     * Cancels an ongoing drag and drop operation.
22970     * <p>
22971     * A {@link android.view.DragEvent} object with
22972     * {@link android.view.DragEvent#getAction()} value of
22973     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22974     * {@link android.view.DragEvent#getResult()} value of {@code false}
22975     * will be sent to every
22976     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22977     * even if they are not currently visible.
22978     * </p>
22979     * <p>
22980     * This method can be called on any View in the same window as the View on which
22981     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22982     * was called.
22983     * </p>
22984     */
22985    public final void cancelDragAndDrop() {
22986        if (ViewDebug.DEBUG_DRAG) {
22987            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22988        }
22989        if (mAttachInfo == null) {
22990            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22991            return;
22992        }
22993        if (mAttachInfo.mDragToken != null) {
22994            try {
22995                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22996            } catch (Exception e) {
22997                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22998            }
22999            mAttachInfo.mDragToken = null;
23000        } else {
23001            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
23002        }
23003    }
23004
23005    /**
23006     * Updates the drag shadow for the ongoing drag and drop operation.
23007     *
23008     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
23009     * new drag shadow.
23010     */
23011    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
23012        if (ViewDebug.DEBUG_DRAG) {
23013            Log.d(VIEW_LOG_TAG, "updateDragShadow");
23014        }
23015        if (mAttachInfo == null) {
23016            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
23017            return;
23018        }
23019        if (mAttachInfo.mDragToken != null) {
23020            try {
23021                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
23022                try {
23023                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
23024                    shadowBuilder.onDrawShadow(canvas);
23025                } finally {
23026                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
23027                }
23028            } catch (Exception e) {
23029                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
23030            }
23031        } else {
23032            Log.e(VIEW_LOG_TAG, "No active drag");
23033        }
23034    }
23035
23036    /**
23037     * Starts a move from {startX, startY}, the amount of the movement will be the offset
23038     * between {startX, startY} and the new cursor positon.
23039     * @param startX horizontal coordinate where the move started.
23040     * @param startY vertical coordinate where the move started.
23041     * @return whether moving was started successfully.
23042     * @hide
23043     */
23044    public final boolean startMovingTask(float startX, float startY) {
23045        if (ViewDebug.DEBUG_POSITIONING) {
23046            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
23047        }
23048        try {
23049            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
23050        } catch (RemoteException e) {
23051            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
23052        }
23053        return false;
23054    }
23055
23056    /**
23057     * Handles drag events sent by the system following a call to
23058     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
23059     * startDragAndDrop()}.
23060     *<p>
23061     * When the system calls this method, it passes a
23062     * {@link android.view.DragEvent} object. A call to
23063     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
23064     * in DragEvent. The method uses these to determine what is happening in the drag and drop
23065     * operation.
23066     * @param event The {@link android.view.DragEvent} sent by the system.
23067     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
23068     * in DragEvent, indicating the type of drag event represented by this object.
23069     * @return {@code true} if the method was successful, otherwise {@code false}.
23070     * <p>
23071     *  The method should return {@code true} in response to an action type of
23072     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
23073     *  operation.
23074     * </p>
23075     * <p>
23076     *  The method should also return {@code true} in response to an action type of
23077     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
23078     *  {@code false} if it didn't.
23079     * </p>
23080     * <p>
23081     *  For all other events, the return value is ignored.
23082     * </p>
23083     */
23084    public boolean onDragEvent(DragEvent event) {
23085        return false;
23086    }
23087
23088    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
23089    boolean dispatchDragEnterExitInPreN(DragEvent event) {
23090        return callDragEventHandler(event);
23091    }
23092
23093    /**
23094     * Detects if this View is enabled and has a drag event listener.
23095     * If both are true, then it calls the drag event listener with the
23096     * {@link android.view.DragEvent} it received. If the drag event listener returns
23097     * {@code true}, then dispatchDragEvent() returns {@code true}.
23098     * <p>
23099     * For all other cases, the method calls the
23100     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
23101     * method and returns its result.
23102     * </p>
23103     * <p>
23104     * This ensures that a drag event is always consumed, even if the View does not have a drag
23105     * event listener. However, if the View has a listener and the listener returns true, then
23106     * onDragEvent() is not called.
23107     * </p>
23108     */
23109    public boolean dispatchDragEvent(DragEvent event) {
23110        event.mEventHandlerWasCalled = true;
23111        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
23112            event.mAction == DragEvent.ACTION_DROP) {
23113            // About to deliver an event with coordinates to this view. Notify that now this view
23114            // has drag focus. This will send exit/enter events as needed.
23115            getViewRootImpl().setDragFocus(this, event);
23116        }
23117        return callDragEventHandler(event);
23118    }
23119
23120    final boolean callDragEventHandler(DragEvent event) {
23121        final boolean result;
23122
23123        ListenerInfo li = mListenerInfo;
23124        //noinspection SimplifiableIfStatement
23125        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
23126                && li.mOnDragListener.onDrag(this, event)) {
23127            result = true;
23128        } else {
23129            result = onDragEvent(event);
23130        }
23131
23132        switch (event.mAction) {
23133            case DragEvent.ACTION_DRAG_ENTERED: {
23134                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
23135                refreshDrawableState();
23136            } break;
23137            case DragEvent.ACTION_DRAG_EXITED: {
23138                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
23139                refreshDrawableState();
23140            } break;
23141            case DragEvent.ACTION_DRAG_ENDED: {
23142                mPrivateFlags2 &= ~View.DRAG_MASK;
23143                refreshDrawableState();
23144            } break;
23145        }
23146
23147        return result;
23148    }
23149
23150    boolean canAcceptDrag() {
23151        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
23152    }
23153
23154    /**
23155     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
23156     * it is ever exposed at all.
23157     * @hide
23158     */
23159    public void onCloseSystemDialogs(String reason) {
23160    }
23161
23162    /**
23163     * Given a Drawable whose bounds have been set to draw into this view,
23164     * update a Region being computed for
23165     * {@link #gatherTransparentRegion(android.graphics.Region)} so
23166     * that any non-transparent parts of the Drawable are removed from the
23167     * given transparent region.
23168     *
23169     * @param dr The Drawable whose transparency is to be applied to the region.
23170     * @param region A Region holding the current transparency information,
23171     * where any parts of the region that are set are considered to be
23172     * transparent.  On return, this region will be modified to have the
23173     * transparency information reduced by the corresponding parts of the
23174     * Drawable that are not transparent.
23175     * {@hide}
23176     */
23177    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
23178        if (DBG) {
23179            Log.i("View", "Getting transparent region for: " + this);
23180        }
23181        final Region r = dr.getTransparentRegion();
23182        final Rect db = dr.getBounds();
23183        final AttachInfo attachInfo = mAttachInfo;
23184        if (r != null && attachInfo != null) {
23185            final int w = getRight()-getLeft();
23186            final int h = getBottom()-getTop();
23187            if (db.left > 0) {
23188                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
23189                r.op(0, 0, db.left, h, Region.Op.UNION);
23190            }
23191            if (db.right < w) {
23192                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
23193                r.op(db.right, 0, w, h, Region.Op.UNION);
23194            }
23195            if (db.top > 0) {
23196                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
23197                r.op(0, 0, w, db.top, Region.Op.UNION);
23198            }
23199            if (db.bottom < h) {
23200                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
23201                r.op(0, db.bottom, w, h, Region.Op.UNION);
23202            }
23203            final int[] location = attachInfo.mTransparentLocation;
23204            getLocationInWindow(location);
23205            r.translate(location[0], location[1]);
23206            region.op(r, Region.Op.INTERSECT);
23207        } else {
23208            region.op(db, Region.Op.DIFFERENCE);
23209        }
23210    }
23211
23212    private void checkForLongClick(int delayOffset, float x, float y) {
23213        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
23214            mHasPerformedLongPress = false;
23215
23216            if (mPendingCheckForLongPress == null) {
23217                mPendingCheckForLongPress = new CheckForLongPress();
23218            }
23219            mPendingCheckForLongPress.setAnchor(x, y);
23220            mPendingCheckForLongPress.rememberWindowAttachCount();
23221            mPendingCheckForLongPress.rememberPressedState();
23222            postDelayed(mPendingCheckForLongPress,
23223                    ViewConfiguration.getLongPressTimeout() - delayOffset);
23224        }
23225    }
23226
23227    /**
23228     * Inflate a view from an XML resource.  This convenience method wraps the {@link
23229     * LayoutInflater} class, which provides a full range of options for view inflation.
23230     *
23231     * @param context The Context object for your activity or application.
23232     * @param resource The resource ID to inflate
23233     * @param root A view group that will be the parent.  Used to properly inflate the
23234     * layout_* parameters.
23235     * @see LayoutInflater
23236     */
23237    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
23238        LayoutInflater factory = LayoutInflater.from(context);
23239        return factory.inflate(resource, root);
23240    }
23241
23242    /**
23243     * Scroll the view with standard behavior for scrolling beyond the normal
23244     * content boundaries. Views that call this method should override
23245     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
23246     * results of an over-scroll operation.
23247     *
23248     * Views can use this method to handle any touch or fling-based scrolling.
23249     *
23250     * @param deltaX Change in X in pixels
23251     * @param deltaY Change in Y in pixels
23252     * @param scrollX Current X scroll value in pixels before applying deltaX
23253     * @param scrollY Current Y scroll value in pixels before applying deltaY
23254     * @param scrollRangeX Maximum content scroll range along the X axis
23255     * @param scrollRangeY Maximum content scroll range along the Y axis
23256     * @param maxOverScrollX Number of pixels to overscroll by in either direction
23257     *          along the X axis.
23258     * @param maxOverScrollY Number of pixels to overscroll by in either direction
23259     *          along the Y axis.
23260     * @param isTouchEvent true if this scroll operation is the result of a touch event.
23261     * @return true if scrolling was clamped to an over-scroll boundary along either
23262     *          axis, false otherwise.
23263     */
23264    @SuppressWarnings({"UnusedParameters"})
23265    protected boolean overScrollBy(int deltaX, int deltaY,
23266            int scrollX, int scrollY,
23267            int scrollRangeX, int scrollRangeY,
23268            int maxOverScrollX, int maxOverScrollY,
23269            boolean isTouchEvent) {
23270        final int overScrollMode = mOverScrollMode;
23271        final boolean canScrollHorizontal =
23272                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
23273        final boolean canScrollVertical =
23274                computeVerticalScrollRange() > computeVerticalScrollExtent();
23275        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
23276                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
23277        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
23278                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
23279
23280        int newScrollX = scrollX + deltaX;
23281        if (!overScrollHorizontal) {
23282            maxOverScrollX = 0;
23283        }
23284
23285        int newScrollY = scrollY + deltaY;
23286        if (!overScrollVertical) {
23287            maxOverScrollY = 0;
23288        }
23289
23290        // Clamp values if at the limits and record
23291        final int left = -maxOverScrollX;
23292        final int right = maxOverScrollX + scrollRangeX;
23293        final int top = -maxOverScrollY;
23294        final int bottom = maxOverScrollY + scrollRangeY;
23295
23296        boolean clampedX = false;
23297        if (newScrollX > right) {
23298            newScrollX = right;
23299            clampedX = true;
23300        } else if (newScrollX < left) {
23301            newScrollX = left;
23302            clampedX = true;
23303        }
23304
23305        boolean clampedY = false;
23306        if (newScrollY > bottom) {
23307            newScrollY = bottom;
23308            clampedY = true;
23309        } else if (newScrollY < top) {
23310            newScrollY = top;
23311            clampedY = true;
23312        }
23313
23314        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
23315
23316        return clampedX || clampedY;
23317    }
23318
23319    /**
23320     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
23321     * respond to the results of an over-scroll operation.
23322     *
23323     * @param scrollX New X scroll value in pixels
23324     * @param scrollY New Y scroll value in pixels
23325     * @param clampedX True if scrollX was clamped to an over-scroll boundary
23326     * @param clampedY True if scrollY was clamped to an over-scroll boundary
23327     */
23328    protected void onOverScrolled(int scrollX, int scrollY,
23329            boolean clampedX, boolean clampedY) {
23330        // Intentionally empty.
23331    }
23332
23333    /**
23334     * Returns the over-scroll mode for this view. The result will be
23335     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23336     * (allow over-scrolling only if the view content is larger than the container),
23337     * or {@link #OVER_SCROLL_NEVER}.
23338     *
23339     * @return This view's over-scroll mode.
23340     */
23341    public int getOverScrollMode() {
23342        return mOverScrollMode;
23343    }
23344
23345    /**
23346     * Set the over-scroll mode for this view. Valid over-scroll modes are
23347     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23348     * (allow over-scrolling only if the view content is larger than the container),
23349     * or {@link #OVER_SCROLL_NEVER}.
23350     *
23351     * Setting the over-scroll mode of a view will have an effect only if the
23352     * view is capable of scrolling.
23353     *
23354     * @param overScrollMode The new over-scroll mode for this view.
23355     */
23356    public void setOverScrollMode(int overScrollMode) {
23357        if (overScrollMode != OVER_SCROLL_ALWAYS &&
23358                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
23359                overScrollMode != OVER_SCROLL_NEVER) {
23360            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
23361        }
23362        mOverScrollMode = overScrollMode;
23363    }
23364
23365    /**
23366     * Enable or disable nested scrolling for this view.
23367     *
23368     * <p>If this property is set to true the view will be permitted to initiate nested
23369     * scrolling operations with a compatible parent view in the current hierarchy. If this
23370     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
23371     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
23372     * the nested scroll.</p>
23373     *
23374     * @param enabled true to enable nested scrolling, false to disable
23375     *
23376     * @see #isNestedScrollingEnabled()
23377     */
23378    public void setNestedScrollingEnabled(boolean enabled) {
23379        if (enabled) {
23380            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
23381        } else {
23382            stopNestedScroll();
23383            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
23384        }
23385    }
23386
23387    /**
23388     * Returns true if nested scrolling is enabled for this view.
23389     *
23390     * <p>If nested scrolling is enabled and this View class implementation supports it,
23391     * this view will act as a nested scrolling child view when applicable, forwarding data
23392     * about the scroll operation in progress to a compatible and cooperating nested scrolling
23393     * parent.</p>
23394     *
23395     * @return true if nested scrolling is enabled
23396     *
23397     * @see #setNestedScrollingEnabled(boolean)
23398     */
23399    public boolean isNestedScrollingEnabled() {
23400        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
23401                PFLAG3_NESTED_SCROLLING_ENABLED;
23402    }
23403
23404    /**
23405     * Begin a nestable scroll operation along the given axes.
23406     *
23407     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
23408     *
23409     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
23410     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
23411     * In the case of touch scrolling the nested scroll will be terminated automatically in
23412     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
23413     * In the event of programmatic scrolling the caller must explicitly call
23414     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
23415     *
23416     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
23417     * If it returns false the caller may ignore the rest of this contract until the next scroll.
23418     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
23419     *
23420     * <p>At each incremental step of the scroll the caller should invoke
23421     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
23422     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
23423     * parent at least partially consumed the scroll and the caller should adjust the amount it
23424     * scrolls by.</p>
23425     *
23426     * <p>After applying the remainder of the scroll delta the caller should invoke
23427     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
23428     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
23429     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
23430     * </p>
23431     *
23432     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
23433     *             {@link #SCROLL_AXIS_VERTICAL}.
23434     * @return true if a cooperative parent was found and nested scrolling has been enabled for
23435     *         the current gesture.
23436     *
23437     * @see #stopNestedScroll()
23438     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23439     * @see #dispatchNestedScroll(int, int, int, int, int[])
23440     */
23441    public boolean startNestedScroll(int axes) {
23442        if (hasNestedScrollingParent()) {
23443            // Already in progress
23444            return true;
23445        }
23446        if (isNestedScrollingEnabled()) {
23447            ViewParent p = getParent();
23448            View child = this;
23449            while (p != null) {
23450                try {
23451                    if (p.onStartNestedScroll(child, this, axes)) {
23452                        mNestedScrollingParent = p;
23453                        p.onNestedScrollAccepted(child, this, axes);
23454                        return true;
23455                    }
23456                } catch (AbstractMethodError e) {
23457                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
23458                            "method onStartNestedScroll", e);
23459                    // Allow the search upward to continue
23460                }
23461                if (p instanceof View) {
23462                    child = (View) p;
23463                }
23464                p = p.getParent();
23465            }
23466        }
23467        return false;
23468    }
23469
23470    /**
23471     * Stop a nested scroll in progress.
23472     *
23473     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
23474     *
23475     * @see #startNestedScroll(int)
23476     */
23477    public void stopNestedScroll() {
23478        if (mNestedScrollingParent != null) {
23479            mNestedScrollingParent.onStopNestedScroll(this);
23480            mNestedScrollingParent = null;
23481        }
23482    }
23483
23484    /**
23485     * Returns true if this view has a nested scrolling parent.
23486     *
23487     * <p>The presence of a nested scrolling parent indicates that this view has initiated
23488     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
23489     *
23490     * @return whether this view has a nested scrolling parent
23491     */
23492    public boolean hasNestedScrollingParent() {
23493        return mNestedScrollingParent != null;
23494    }
23495
23496    /**
23497     * Dispatch one step of a nested scroll in progress.
23498     *
23499     * <p>Implementations of views that support nested scrolling should call this to report
23500     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
23501     * is not currently in progress or nested scrolling is not
23502     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
23503     *
23504     * <p>Compatible View implementations should also call
23505     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
23506     * consuming a component of the scroll event themselves.</p>
23507     *
23508     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
23509     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
23510     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
23511     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
23512     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23513     *                       in local view coordinates of this view from before this operation
23514     *                       to after it completes. View implementations may use this to adjust
23515     *                       expected input coordinate tracking.
23516     * @return true if the event was dispatched, false if it could not be dispatched.
23517     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23518     */
23519    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
23520            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
23521        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23522            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
23523                int startX = 0;
23524                int startY = 0;
23525                if (offsetInWindow != null) {
23526                    getLocationInWindow(offsetInWindow);
23527                    startX = offsetInWindow[0];
23528                    startY = offsetInWindow[1];
23529                }
23530
23531                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
23532                        dxUnconsumed, dyUnconsumed);
23533
23534                if (offsetInWindow != null) {
23535                    getLocationInWindow(offsetInWindow);
23536                    offsetInWindow[0] -= startX;
23537                    offsetInWindow[1] -= startY;
23538                }
23539                return true;
23540            } else if (offsetInWindow != null) {
23541                // No motion, no dispatch. Keep offsetInWindow up to date.
23542                offsetInWindow[0] = 0;
23543                offsetInWindow[1] = 0;
23544            }
23545        }
23546        return false;
23547    }
23548
23549    /**
23550     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
23551     *
23552     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
23553     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
23554     * scrolling operation to consume some or all of the scroll operation before the child view
23555     * consumes it.</p>
23556     *
23557     * @param dx Horizontal scroll distance in pixels
23558     * @param dy Vertical scroll distance in pixels
23559     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
23560     *                 and consumed[1] the consumed dy.
23561     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23562     *                       in local view coordinates of this view from before this operation
23563     *                       to after it completes. View implementations may use this to adjust
23564     *                       expected input coordinate tracking.
23565     * @return true if the parent consumed some or all of the scroll delta
23566     * @see #dispatchNestedScroll(int, int, int, int, int[])
23567     */
23568    public boolean dispatchNestedPreScroll(int dx, int dy,
23569            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
23570        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23571            if (dx != 0 || dy != 0) {
23572                int startX = 0;
23573                int startY = 0;
23574                if (offsetInWindow != null) {
23575                    getLocationInWindow(offsetInWindow);
23576                    startX = offsetInWindow[0];
23577                    startY = offsetInWindow[1];
23578                }
23579
23580                if (consumed == null) {
23581                    if (mTempNestedScrollConsumed == null) {
23582                        mTempNestedScrollConsumed = new int[2];
23583                    }
23584                    consumed = mTempNestedScrollConsumed;
23585                }
23586                consumed[0] = 0;
23587                consumed[1] = 0;
23588                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
23589
23590                if (offsetInWindow != null) {
23591                    getLocationInWindow(offsetInWindow);
23592                    offsetInWindow[0] -= startX;
23593                    offsetInWindow[1] -= startY;
23594                }
23595                return consumed[0] != 0 || consumed[1] != 0;
23596            } else if (offsetInWindow != null) {
23597                offsetInWindow[0] = 0;
23598                offsetInWindow[1] = 0;
23599            }
23600        }
23601        return false;
23602    }
23603
23604    /**
23605     * Dispatch a fling to a nested scrolling parent.
23606     *
23607     * <p>This method should be used to indicate that a nested scrolling child has detected
23608     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
23609     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
23610     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
23611     * along a scrollable axis.</p>
23612     *
23613     * <p>If a nested scrolling child view would normally fling but it is at the edge of
23614     * its own content, it can use this method to delegate the fling to its nested scrolling
23615     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
23616     *
23617     * @param velocityX Horizontal fling velocity in pixels per second
23618     * @param velocityY Vertical fling velocity in pixels per second
23619     * @param consumed true if the child consumed the fling, false otherwise
23620     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
23621     */
23622    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
23623        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23624            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
23625        }
23626        return false;
23627    }
23628
23629    /**
23630     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
23631     *
23632     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
23633     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
23634     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
23635     * before the child view consumes it. If this method returns <code>true</code>, a nested
23636     * parent view consumed the fling and this view should not scroll as a result.</p>
23637     *
23638     * <p>For a better user experience, only one view in a nested scrolling chain should consume
23639     * the fling at a time. If a parent view consumed the fling this method will return false.
23640     * Custom view implementations should account for this in two ways:</p>
23641     *
23642     * <ul>
23643     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
23644     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
23645     *     position regardless.</li>
23646     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
23647     *     even to settle back to a valid idle position.</li>
23648     * </ul>
23649     *
23650     * <p>Views should also not offer fling velocities to nested parent views along an axis
23651     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
23652     * should not offer a horizontal fling velocity to its parents since scrolling along that
23653     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
23654     *
23655     * @param velocityX Horizontal fling velocity in pixels per second
23656     * @param velocityY Vertical fling velocity in pixels per second
23657     * @return true if a nested scrolling parent consumed the fling
23658     */
23659    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
23660        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23661            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
23662        }
23663        return false;
23664    }
23665
23666    /**
23667     * Gets a scale factor that determines the distance the view should scroll
23668     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
23669     * @return The vertical scroll scale factor.
23670     * @hide
23671     */
23672    protected float getVerticalScrollFactor() {
23673        if (mVerticalScrollFactor == 0) {
23674            TypedValue outValue = new TypedValue();
23675            if (!mContext.getTheme().resolveAttribute(
23676                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
23677                throw new IllegalStateException(
23678                        "Expected theme to define listPreferredItemHeight.");
23679            }
23680            mVerticalScrollFactor = outValue.getDimension(
23681                    mContext.getResources().getDisplayMetrics());
23682        }
23683        return mVerticalScrollFactor;
23684    }
23685
23686    /**
23687     * Gets a scale factor that determines the distance the view should scroll
23688     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
23689     * @return The horizontal scroll scale factor.
23690     * @hide
23691     */
23692    protected float getHorizontalScrollFactor() {
23693        // TODO: Should use something else.
23694        return getVerticalScrollFactor();
23695    }
23696
23697    /**
23698     * Return the value specifying the text direction or policy that was set with
23699     * {@link #setTextDirection(int)}.
23700     *
23701     * @return the defined text direction. It can be one of:
23702     *
23703     * {@link #TEXT_DIRECTION_INHERIT},
23704     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23705     * {@link #TEXT_DIRECTION_ANY_RTL},
23706     * {@link #TEXT_DIRECTION_LTR},
23707     * {@link #TEXT_DIRECTION_RTL},
23708     * {@link #TEXT_DIRECTION_LOCALE},
23709     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23710     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23711     *
23712     * @attr ref android.R.styleable#View_textDirection
23713     *
23714     * @hide
23715     */
23716    @ViewDebug.ExportedProperty(category = "text", mapping = {
23717            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23718            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23719            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23720            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23721            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23722            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23723            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23724            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23725    })
23726    public int getRawTextDirection() {
23727        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
23728    }
23729
23730    /**
23731     * Set the text direction.
23732     *
23733     * @param textDirection the direction to set. Should be one of:
23734     *
23735     * {@link #TEXT_DIRECTION_INHERIT},
23736     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23737     * {@link #TEXT_DIRECTION_ANY_RTL},
23738     * {@link #TEXT_DIRECTION_LTR},
23739     * {@link #TEXT_DIRECTION_RTL},
23740     * {@link #TEXT_DIRECTION_LOCALE}
23741     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23742     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
23743     *
23744     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
23745     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
23746     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
23747     *
23748     * @attr ref android.R.styleable#View_textDirection
23749     */
23750    public void setTextDirection(int textDirection) {
23751        if (getRawTextDirection() != textDirection) {
23752            // Reset the current text direction and the resolved one
23753            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
23754            resetResolvedTextDirection();
23755            // Set the new text direction
23756            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
23757            // Do resolution
23758            resolveTextDirection();
23759            // Notify change
23760            onRtlPropertiesChanged(getLayoutDirection());
23761            // Refresh
23762            requestLayout();
23763            invalidate(true);
23764        }
23765    }
23766
23767    /**
23768     * Return the resolved text direction.
23769     *
23770     * @return the resolved text direction. Returns one of:
23771     *
23772     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23773     * {@link #TEXT_DIRECTION_ANY_RTL},
23774     * {@link #TEXT_DIRECTION_LTR},
23775     * {@link #TEXT_DIRECTION_RTL},
23776     * {@link #TEXT_DIRECTION_LOCALE},
23777     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23778     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23779     *
23780     * @attr ref android.R.styleable#View_textDirection
23781     */
23782    @ViewDebug.ExportedProperty(category = "text", mapping = {
23783            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23784            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23785            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23786            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23787            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23788            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23789            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23790            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23791    })
23792    public int getTextDirection() {
23793        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23794    }
23795
23796    /**
23797     * Resolve the text direction.
23798     *
23799     * @return true if resolution has been done, false otherwise.
23800     *
23801     * @hide
23802     */
23803    public boolean resolveTextDirection() {
23804        // Reset any previous text direction resolution
23805        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23806
23807        if (hasRtlSupport()) {
23808            // Set resolved text direction flag depending on text direction flag
23809            final int textDirection = getRawTextDirection();
23810            switch(textDirection) {
23811                case TEXT_DIRECTION_INHERIT:
23812                    if (!canResolveTextDirection()) {
23813                        // We cannot do the resolution if there is no parent, so use the default one
23814                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23815                        // Resolution will need to happen again later
23816                        return false;
23817                    }
23818
23819                    // Parent has not yet resolved, so we still return the default
23820                    try {
23821                        if (!mParent.isTextDirectionResolved()) {
23822                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23823                            // Resolution will need to happen again later
23824                            return false;
23825                        }
23826                    } catch (AbstractMethodError e) {
23827                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23828                                " does not fully implement ViewParent", e);
23829                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23830                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23831                        return true;
23832                    }
23833
23834                    // Set current resolved direction to the same value as the parent's one
23835                    int parentResolvedDirection;
23836                    try {
23837                        parentResolvedDirection = mParent.getTextDirection();
23838                    } catch (AbstractMethodError e) {
23839                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23840                                " does not fully implement ViewParent", e);
23841                        parentResolvedDirection = TEXT_DIRECTION_LTR;
23842                    }
23843                    switch (parentResolvedDirection) {
23844                        case TEXT_DIRECTION_FIRST_STRONG:
23845                        case TEXT_DIRECTION_ANY_RTL:
23846                        case TEXT_DIRECTION_LTR:
23847                        case TEXT_DIRECTION_RTL:
23848                        case TEXT_DIRECTION_LOCALE:
23849                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
23850                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
23851                            mPrivateFlags2 |=
23852                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23853                            break;
23854                        default:
23855                            // Default resolved direction is "first strong" heuristic
23856                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23857                    }
23858                    break;
23859                case TEXT_DIRECTION_FIRST_STRONG:
23860                case TEXT_DIRECTION_ANY_RTL:
23861                case TEXT_DIRECTION_LTR:
23862                case TEXT_DIRECTION_RTL:
23863                case TEXT_DIRECTION_LOCALE:
23864                case TEXT_DIRECTION_FIRST_STRONG_LTR:
23865                case TEXT_DIRECTION_FIRST_STRONG_RTL:
23866                    // Resolved direction is the same as text direction
23867                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23868                    break;
23869                default:
23870                    // Default resolved direction is "first strong" heuristic
23871                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23872            }
23873        } else {
23874            // Default resolved direction is "first strong" heuristic
23875            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23876        }
23877
23878        // Set to resolved
23879        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23880        return true;
23881    }
23882
23883    /**
23884     * Check if text direction resolution can be done.
23885     *
23886     * @return true if text direction resolution can be done otherwise return false.
23887     */
23888    public boolean canResolveTextDirection() {
23889        switch (getRawTextDirection()) {
23890            case TEXT_DIRECTION_INHERIT:
23891                if (mParent != null) {
23892                    try {
23893                        return mParent.canResolveTextDirection();
23894                    } catch (AbstractMethodError e) {
23895                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23896                                " does not fully implement ViewParent", e);
23897                    }
23898                }
23899                return false;
23900
23901            default:
23902                return true;
23903        }
23904    }
23905
23906    /**
23907     * Reset resolved text direction. Text direction will be resolved during a call to
23908     * {@link #onMeasure(int, int)}.
23909     *
23910     * @hide
23911     */
23912    public void resetResolvedTextDirection() {
23913        // Reset any previous text direction resolution
23914        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23915        // Set to default value
23916        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23917    }
23918
23919    /**
23920     * @return true if text direction is inherited.
23921     *
23922     * @hide
23923     */
23924    public boolean isTextDirectionInherited() {
23925        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23926    }
23927
23928    /**
23929     * @return true if text direction is resolved.
23930     */
23931    public boolean isTextDirectionResolved() {
23932        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23933    }
23934
23935    /**
23936     * Return the value specifying the text alignment or policy that was set with
23937     * {@link #setTextAlignment(int)}.
23938     *
23939     * @return the defined text alignment. It can be one of:
23940     *
23941     * {@link #TEXT_ALIGNMENT_INHERIT},
23942     * {@link #TEXT_ALIGNMENT_GRAVITY},
23943     * {@link #TEXT_ALIGNMENT_CENTER},
23944     * {@link #TEXT_ALIGNMENT_TEXT_START},
23945     * {@link #TEXT_ALIGNMENT_TEXT_END},
23946     * {@link #TEXT_ALIGNMENT_VIEW_START},
23947     * {@link #TEXT_ALIGNMENT_VIEW_END}
23948     *
23949     * @attr ref android.R.styleable#View_textAlignment
23950     *
23951     * @hide
23952     */
23953    @ViewDebug.ExportedProperty(category = "text", mapping = {
23954            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23955            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23956            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23957            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23958            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23959            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23960            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23961    })
23962    @TextAlignment
23963    public int getRawTextAlignment() {
23964        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23965    }
23966
23967    /**
23968     * Set the text alignment.
23969     *
23970     * @param textAlignment The text alignment to set. Should be one of
23971     *
23972     * {@link #TEXT_ALIGNMENT_INHERIT},
23973     * {@link #TEXT_ALIGNMENT_GRAVITY},
23974     * {@link #TEXT_ALIGNMENT_CENTER},
23975     * {@link #TEXT_ALIGNMENT_TEXT_START},
23976     * {@link #TEXT_ALIGNMENT_TEXT_END},
23977     * {@link #TEXT_ALIGNMENT_VIEW_START},
23978     * {@link #TEXT_ALIGNMENT_VIEW_END}
23979     *
23980     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23981     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23982     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23983     *
23984     * @attr ref android.R.styleable#View_textAlignment
23985     */
23986    public void setTextAlignment(@TextAlignment int textAlignment) {
23987        if (textAlignment != getRawTextAlignment()) {
23988            // Reset the current and resolved text alignment
23989            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23990            resetResolvedTextAlignment();
23991            // Set the new text alignment
23992            mPrivateFlags2 |=
23993                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23994            // Do resolution
23995            resolveTextAlignment();
23996            // Notify change
23997            onRtlPropertiesChanged(getLayoutDirection());
23998            // Refresh
23999            requestLayout();
24000            invalidate(true);
24001        }
24002    }
24003
24004    /**
24005     * Return the resolved text alignment.
24006     *
24007     * @return the resolved text alignment. Returns one of:
24008     *
24009     * {@link #TEXT_ALIGNMENT_GRAVITY},
24010     * {@link #TEXT_ALIGNMENT_CENTER},
24011     * {@link #TEXT_ALIGNMENT_TEXT_START},
24012     * {@link #TEXT_ALIGNMENT_TEXT_END},
24013     * {@link #TEXT_ALIGNMENT_VIEW_START},
24014     * {@link #TEXT_ALIGNMENT_VIEW_END}
24015     *
24016     * @attr ref android.R.styleable#View_textAlignment
24017     */
24018    @ViewDebug.ExportedProperty(category = "text", mapping = {
24019            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
24020            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
24021            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
24022            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
24023            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
24024            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
24025            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
24026    })
24027    @TextAlignment
24028    public int getTextAlignment() {
24029        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
24030                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
24031    }
24032
24033    /**
24034     * Resolve the text alignment.
24035     *
24036     * @return true if resolution has been done, false otherwise.
24037     *
24038     * @hide
24039     */
24040    public boolean resolveTextAlignment() {
24041        // Reset any previous text alignment resolution
24042        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
24043
24044        if (hasRtlSupport()) {
24045            // Set resolved text alignment flag depending on text alignment flag
24046            final int textAlignment = getRawTextAlignment();
24047            switch (textAlignment) {
24048                case TEXT_ALIGNMENT_INHERIT:
24049                    // Check if we can resolve the text alignment
24050                    if (!canResolveTextAlignment()) {
24051                        // We cannot do the resolution if there is no parent so use the default
24052                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24053                        // Resolution will need to happen again later
24054                        return false;
24055                    }
24056
24057                    // Parent has not yet resolved, so we still return the default
24058                    try {
24059                        if (!mParent.isTextAlignmentResolved()) {
24060                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24061                            // Resolution will need to happen again later
24062                            return false;
24063                        }
24064                    } catch (AbstractMethodError e) {
24065                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24066                                " does not fully implement ViewParent", e);
24067                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
24068                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24069                        return true;
24070                    }
24071
24072                    int parentResolvedTextAlignment;
24073                    try {
24074                        parentResolvedTextAlignment = mParent.getTextAlignment();
24075                    } catch (AbstractMethodError e) {
24076                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24077                                " does not fully implement ViewParent", e);
24078                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
24079                    }
24080                    switch (parentResolvedTextAlignment) {
24081                        case TEXT_ALIGNMENT_GRAVITY:
24082                        case TEXT_ALIGNMENT_TEXT_START:
24083                        case TEXT_ALIGNMENT_TEXT_END:
24084                        case TEXT_ALIGNMENT_CENTER:
24085                        case TEXT_ALIGNMENT_VIEW_START:
24086                        case TEXT_ALIGNMENT_VIEW_END:
24087                            // Resolved text alignment is the same as the parent resolved
24088                            // text alignment
24089                            mPrivateFlags2 |=
24090                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
24091                            break;
24092                        default:
24093                            // Use default resolved text alignment
24094                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24095                    }
24096                    break;
24097                case TEXT_ALIGNMENT_GRAVITY:
24098                case TEXT_ALIGNMENT_TEXT_START:
24099                case TEXT_ALIGNMENT_TEXT_END:
24100                case TEXT_ALIGNMENT_CENTER:
24101                case TEXT_ALIGNMENT_VIEW_START:
24102                case TEXT_ALIGNMENT_VIEW_END:
24103                    // Resolved text alignment is the same as text alignment
24104                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
24105                    break;
24106                default:
24107                    // Use default resolved text alignment
24108                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24109            }
24110        } else {
24111            // Use default resolved text alignment
24112            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24113        }
24114
24115        // Set the resolved
24116        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
24117        return true;
24118    }
24119
24120    /**
24121     * Check if text alignment resolution can be done.
24122     *
24123     * @return true if text alignment resolution can be done otherwise return false.
24124     */
24125    public boolean canResolveTextAlignment() {
24126        switch (getRawTextAlignment()) {
24127            case TEXT_DIRECTION_INHERIT:
24128                if (mParent != null) {
24129                    try {
24130                        return mParent.canResolveTextAlignment();
24131                    } catch (AbstractMethodError e) {
24132                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24133                                " does not fully implement ViewParent", e);
24134                    }
24135                }
24136                return false;
24137
24138            default:
24139                return true;
24140        }
24141    }
24142
24143    /**
24144     * Reset resolved text alignment. Text alignment will be resolved during a call to
24145     * {@link #onMeasure(int, int)}.
24146     *
24147     * @hide
24148     */
24149    public void resetResolvedTextAlignment() {
24150        // Reset any previous text alignment resolution
24151        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
24152        // Set to default
24153        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24154    }
24155
24156    /**
24157     * @return true if text alignment is inherited.
24158     *
24159     * @hide
24160     */
24161    public boolean isTextAlignmentInherited() {
24162        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
24163    }
24164
24165    /**
24166     * @return true if text alignment is resolved.
24167     */
24168    public boolean isTextAlignmentResolved() {
24169        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
24170    }
24171
24172    /**
24173     * Generate a value suitable for use in {@link #setId(int)}.
24174     * This value will not collide with ID values generated at build time by aapt for R.id.
24175     *
24176     * @return a generated ID value
24177     */
24178    public static int generateViewId() {
24179        for (;;) {
24180            final int result = sNextGeneratedId.get();
24181            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
24182            int newValue = result + 1;
24183            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
24184            if (sNextGeneratedId.compareAndSet(result, newValue)) {
24185                return result;
24186            }
24187        }
24188    }
24189
24190    private static boolean isViewIdGenerated(int id) {
24191        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
24192    }
24193
24194    /**
24195     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
24196     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
24197     *                           a normal View or a ViewGroup with
24198     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
24199     * @hide
24200     */
24201    public void captureTransitioningViews(List<View> transitioningViews) {
24202        if (getVisibility() == View.VISIBLE) {
24203            transitioningViews.add(this);
24204        }
24205    }
24206
24207    /**
24208     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
24209     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
24210     * @hide
24211     */
24212    public void findNamedViews(Map<String, View> namedElements) {
24213        if (getVisibility() == VISIBLE || mGhostView != null) {
24214            String transitionName = getTransitionName();
24215            if (transitionName != null) {
24216                namedElements.put(transitionName, this);
24217            }
24218        }
24219    }
24220
24221    /**
24222     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
24223     * The default implementation does not care the location or event types, but some subclasses
24224     * may use it (such as WebViews).
24225     * @param event The MotionEvent from a mouse
24226     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
24227     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
24228     * @see PointerIcon
24229     */
24230    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
24231        final float x = event.getX(pointerIndex);
24232        final float y = event.getY(pointerIndex);
24233        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
24234            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
24235        }
24236        return mPointerIcon;
24237    }
24238
24239    /**
24240     * Set the pointer icon for the current view.
24241     * Passing {@code null} will restore the pointer icon to its default value.
24242     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
24243     */
24244    public void setPointerIcon(PointerIcon pointerIcon) {
24245        mPointerIcon = pointerIcon;
24246        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
24247            return;
24248        }
24249        try {
24250            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
24251        } catch (RemoteException e) {
24252        }
24253    }
24254
24255    /**
24256     * Gets the pointer icon for the current view.
24257     */
24258    public PointerIcon getPointerIcon() {
24259        return mPointerIcon;
24260    }
24261
24262    /**
24263     * Checks pointer capture status.
24264     *
24265     * @return true if the view has pointer capture.
24266     * @see #requestPointerCapture()
24267     * @see #hasPointerCapture()
24268     */
24269    public boolean hasPointerCapture() {
24270        final ViewRootImpl viewRootImpl = getViewRootImpl();
24271        if (viewRootImpl == null) {
24272            return false;
24273        }
24274        return viewRootImpl.hasPointerCapture();
24275    }
24276
24277    /**
24278     * Requests pointer capture mode.
24279     * <p>
24280     * When the window has pointer capture, the mouse pointer icon will disappear and will not
24281     * change its position. Further mouse will be dispatched with the source
24282     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
24283     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
24284     * (touchscreens, or stylus) will not be affected.
24285     * <p>
24286     * If the window already has pointer capture, this call does nothing.
24287     * <p>
24288     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
24289     * automatically when the window loses focus.
24290     *
24291     * @see #releasePointerCapture()
24292     * @see #hasPointerCapture()
24293     */
24294    public void requestPointerCapture() {
24295        final ViewRootImpl viewRootImpl = getViewRootImpl();
24296        if (viewRootImpl != null) {
24297            viewRootImpl.requestPointerCapture(true);
24298        }
24299    }
24300
24301
24302    /**
24303     * Releases the pointer capture.
24304     * <p>
24305     * If the window does not have pointer capture, this call will do nothing.
24306     * @see #requestPointerCapture()
24307     * @see #hasPointerCapture()
24308     */
24309    public void releasePointerCapture() {
24310        final ViewRootImpl viewRootImpl = getViewRootImpl();
24311        if (viewRootImpl != null) {
24312            viewRootImpl.requestPointerCapture(false);
24313        }
24314    }
24315
24316    /**
24317     * Called when the window has just acquired or lost pointer capture.
24318     *
24319     * @param hasCapture True if the view now has pointerCapture, false otherwise.
24320     */
24321    @CallSuper
24322    public void onPointerCaptureChange(boolean hasCapture) {
24323    }
24324
24325    /**
24326     * @see #onPointerCaptureChange
24327     */
24328    public void dispatchPointerCaptureChanged(boolean hasCapture) {
24329        onPointerCaptureChange(hasCapture);
24330    }
24331
24332    /**
24333     * Implement this method to handle captured pointer events
24334     *
24335     * @param event The captured pointer event.
24336     * @return True if the event was handled, false otherwise.
24337     * @see #requestPointerCapture()
24338     */
24339    public boolean onCapturedPointerEvent(MotionEvent event) {
24340        return false;
24341    }
24342
24343    /**
24344     * Interface definition for a callback to be invoked when a captured pointer event
24345     * is being dispatched this view. The callback will be invoked before the event is
24346     * given to the view.
24347     */
24348    public interface OnCapturedPointerListener {
24349        /**
24350         * Called when a captured pointer event is dispatched to a view.
24351         * @param view The view this event has been dispatched to.
24352         * @param event The captured event.
24353         * @return True if the listener has consumed the event, false otherwise.
24354         */
24355        boolean onCapturedPointer(View view, MotionEvent event);
24356    }
24357
24358    /**
24359     * Set a listener to receive callbacks when the pointer capture state of a view changes.
24360     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
24361     */
24362    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
24363        getListenerInfo().mOnCapturedPointerListener = l;
24364    }
24365
24366    // Properties
24367    //
24368    /**
24369     * A Property wrapper around the <code>alpha</code> functionality handled by the
24370     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
24371     */
24372    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
24373        @Override
24374        public void setValue(View object, float value) {
24375            object.setAlpha(value);
24376        }
24377
24378        @Override
24379        public Float get(View object) {
24380            return object.getAlpha();
24381        }
24382    };
24383
24384    /**
24385     * A Property wrapper around the <code>translationX</code> functionality handled by the
24386     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
24387     */
24388    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
24389        @Override
24390        public void setValue(View object, float value) {
24391            object.setTranslationX(value);
24392        }
24393
24394                @Override
24395        public Float get(View object) {
24396            return object.getTranslationX();
24397        }
24398    };
24399
24400    /**
24401     * A Property wrapper around the <code>translationY</code> functionality handled by the
24402     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
24403     */
24404    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
24405        @Override
24406        public void setValue(View object, float value) {
24407            object.setTranslationY(value);
24408        }
24409
24410        @Override
24411        public Float get(View object) {
24412            return object.getTranslationY();
24413        }
24414    };
24415
24416    /**
24417     * A Property wrapper around the <code>translationZ</code> functionality handled by the
24418     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
24419     */
24420    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
24421        @Override
24422        public void setValue(View object, float value) {
24423            object.setTranslationZ(value);
24424        }
24425
24426        @Override
24427        public Float get(View object) {
24428            return object.getTranslationZ();
24429        }
24430    };
24431
24432    /**
24433     * A Property wrapper around the <code>x</code> functionality handled by the
24434     * {@link View#setX(float)} and {@link View#getX()} methods.
24435     */
24436    public static final Property<View, Float> X = new FloatProperty<View>("x") {
24437        @Override
24438        public void setValue(View object, float value) {
24439            object.setX(value);
24440        }
24441
24442        @Override
24443        public Float get(View object) {
24444            return object.getX();
24445        }
24446    };
24447
24448    /**
24449     * A Property wrapper around the <code>y</code> functionality handled by the
24450     * {@link View#setY(float)} and {@link View#getY()} methods.
24451     */
24452    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
24453        @Override
24454        public void setValue(View object, float value) {
24455            object.setY(value);
24456        }
24457
24458        @Override
24459        public Float get(View object) {
24460            return object.getY();
24461        }
24462    };
24463
24464    /**
24465     * A Property wrapper around the <code>z</code> functionality handled by the
24466     * {@link View#setZ(float)} and {@link View#getZ()} methods.
24467     */
24468    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
24469        @Override
24470        public void setValue(View object, float value) {
24471            object.setZ(value);
24472        }
24473
24474        @Override
24475        public Float get(View object) {
24476            return object.getZ();
24477        }
24478    };
24479
24480    /**
24481     * A Property wrapper around the <code>rotation</code> functionality handled by the
24482     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
24483     */
24484    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
24485        @Override
24486        public void setValue(View object, float value) {
24487            object.setRotation(value);
24488        }
24489
24490        @Override
24491        public Float get(View object) {
24492            return object.getRotation();
24493        }
24494    };
24495
24496    /**
24497     * A Property wrapper around the <code>rotationX</code> functionality handled by the
24498     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
24499     */
24500    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
24501        @Override
24502        public void setValue(View object, float value) {
24503            object.setRotationX(value);
24504        }
24505
24506        @Override
24507        public Float get(View object) {
24508            return object.getRotationX();
24509        }
24510    };
24511
24512    /**
24513     * A Property wrapper around the <code>rotationY</code> functionality handled by the
24514     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
24515     */
24516    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
24517        @Override
24518        public void setValue(View object, float value) {
24519            object.setRotationY(value);
24520        }
24521
24522        @Override
24523        public Float get(View object) {
24524            return object.getRotationY();
24525        }
24526    };
24527
24528    /**
24529     * A Property wrapper around the <code>scaleX</code> functionality handled by the
24530     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
24531     */
24532    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
24533        @Override
24534        public void setValue(View object, float value) {
24535            object.setScaleX(value);
24536        }
24537
24538        @Override
24539        public Float get(View object) {
24540            return object.getScaleX();
24541        }
24542    };
24543
24544    /**
24545     * A Property wrapper around the <code>scaleY</code> functionality handled by the
24546     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
24547     */
24548    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
24549        @Override
24550        public void setValue(View object, float value) {
24551            object.setScaleY(value);
24552        }
24553
24554        @Override
24555        public Float get(View object) {
24556            return object.getScaleY();
24557        }
24558    };
24559
24560    /**
24561     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
24562     * Each MeasureSpec represents a requirement for either the width or the height.
24563     * A MeasureSpec is comprised of a size and a mode. There are three possible
24564     * modes:
24565     * <dl>
24566     * <dt>UNSPECIFIED</dt>
24567     * <dd>
24568     * The parent has not imposed any constraint on the child. It can be whatever size
24569     * it wants.
24570     * </dd>
24571     *
24572     * <dt>EXACTLY</dt>
24573     * <dd>
24574     * The parent has determined an exact size for the child. The child is going to be
24575     * given those bounds regardless of how big it wants to be.
24576     * </dd>
24577     *
24578     * <dt>AT_MOST</dt>
24579     * <dd>
24580     * The child can be as large as it wants up to the specified size.
24581     * </dd>
24582     * </dl>
24583     *
24584     * MeasureSpecs are implemented as ints to reduce object allocation. This class
24585     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
24586     */
24587    public static class MeasureSpec {
24588        private static final int MODE_SHIFT = 30;
24589        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
24590
24591        /** @hide */
24592        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
24593        @Retention(RetentionPolicy.SOURCE)
24594        public @interface MeasureSpecMode {}
24595
24596        /**
24597         * Measure specification mode: The parent has not imposed any constraint
24598         * on the child. It can be whatever size it wants.
24599         */
24600        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
24601
24602        /**
24603         * Measure specification mode: The parent has determined an exact size
24604         * for the child. The child is going to be given those bounds regardless
24605         * of how big it wants to be.
24606         */
24607        public static final int EXACTLY     = 1 << MODE_SHIFT;
24608
24609        /**
24610         * Measure specification mode: The child can be as large as it wants up
24611         * to the specified size.
24612         */
24613        public static final int AT_MOST     = 2 << MODE_SHIFT;
24614
24615        /**
24616         * Creates a measure specification based on the supplied size and mode.
24617         *
24618         * The mode must always be one of the following:
24619         * <ul>
24620         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
24621         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
24622         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
24623         * </ul>
24624         *
24625         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
24626         * implementation was such that the order of arguments did not matter
24627         * and overflow in either value could impact the resulting MeasureSpec.
24628         * {@link android.widget.RelativeLayout} was affected by this bug.
24629         * Apps targeting API levels greater than 17 will get the fixed, more strict
24630         * behavior.</p>
24631         *
24632         * @param size the size of the measure specification
24633         * @param mode the mode of the measure specification
24634         * @return the measure specification based on size and mode
24635         */
24636        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
24637                                          @MeasureSpecMode int mode) {
24638            if (sUseBrokenMakeMeasureSpec) {
24639                return size + mode;
24640            } else {
24641                return (size & ~MODE_MASK) | (mode & MODE_MASK);
24642            }
24643        }
24644
24645        /**
24646         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
24647         * will automatically get a size of 0. Older apps expect this.
24648         *
24649         * @hide internal use only for compatibility with system widgets and older apps
24650         */
24651        public static int makeSafeMeasureSpec(int size, int mode) {
24652            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
24653                return 0;
24654            }
24655            return makeMeasureSpec(size, mode);
24656        }
24657
24658        /**
24659         * Extracts the mode from the supplied measure specification.
24660         *
24661         * @param measureSpec the measure specification to extract the mode from
24662         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
24663         *         {@link android.view.View.MeasureSpec#AT_MOST} or
24664         *         {@link android.view.View.MeasureSpec#EXACTLY}
24665         */
24666        @MeasureSpecMode
24667        public static int getMode(int measureSpec) {
24668            //noinspection ResourceType
24669            return (measureSpec & MODE_MASK);
24670        }
24671
24672        /**
24673         * Extracts the size from the supplied measure specification.
24674         *
24675         * @param measureSpec the measure specification to extract the size from
24676         * @return the size in pixels defined in the supplied measure specification
24677         */
24678        public static int getSize(int measureSpec) {
24679            return (measureSpec & ~MODE_MASK);
24680        }
24681
24682        static int adjust(int measureSpec, int delta) {
24683            final int mode = getMode(measureSpec);
24684            int size = getSize(measureSpec);
24685            if (mode == UNSPECIFIED) {
24686                // No need to adjust size for UNSPECIFIED mode.
24687                return makeMeasureSpec(size, UNSPECIFIED);
24688            }
24689            size += delta;
24690            if (size < 0) {
24691                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
24692                        ") spec: " + toString(measureSpec) + " delta: " + delta);
24693                size = 0;
24694            }
24695            return makeMeasureSpec(size, mode);
24696        }
24697
24698        /**
24699         * Returns a String representation of the specified measure
24700         * specification.
24701         *
24702         * @param measureSpec the measure specification to convert to a String
24703         * @return a String with the following format: "MeasureSpec: MODE SIZE"
24704         */
24705        public static String toString(int measureSpec) {
24706            int mode = getMode(measureSpec);
24707            int size = getSize(measureSpec);
24708
24709            StringBuilder sb = new StringBuilder("MeasureSpec: ");
24710
24711            if (mode == UNSPECIFIED)
24712                sb.append("UNSPECIFIED ");
24713            else if (mode == EXACTLY)
24714                sb.append("EXACTLY ");
24715            else if (mode == AT_MOST)
24716                sb.append("AT_MOST ");
24717            else
24718                sb.append(mode).append(" ");
24719
24720            sb.append(size);
24721            return sb.toString();
24722        }
24723    }
24724
24725    private final class CheckForLongPress implements Runnable {
24726        private int mOriginalWindowAttachCount;
24727        private float mX;
24728        private float mY;
24729        private boolean mOriginalPressedState;
24730
24731        @Override
24732        public void run() {
24733            if ((mOriginalPressedState == isPressed()) && (mParent != null)
24734                    && mOriginalWindowAttachCount == mWindowAttachCount) {
24735                if (performLongClick(mX, mY)) {
24736                    mHasPerformedLongPress = true;
24737                }
24738            }
24739        }
24740
24741        public void setAnchor(float x, float y) {
24742            mX = x;
24743            mY = y;
24744        }
24745
24746        public void rememberWindowAttachCount() {
24747            mOriginalWindowAttachCount = mWindowAttachCount;
24748        }
24749
24750        public void rememberPressedState() {
24751            mOriginalPressedState = isPressed();
24752        }
24753    }
24754
24755    private final class CheckForTap implements Runnable {
24756        public float x;
24757        public float y;
24758
24759        @Override
24760        public void run() {
24761            mPrivateFlags &= ~PFLAG_PREPRESSED;
24762            setPressed(true, x, y);
24763            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
24764        }
24765    }
24766
24767    private final class PerformClick implements Runnable {
24768        @Override
24769        public void run() {
24770            performClick();
24771        }
24772    }
24773
24774    /**
24775     * This method returns a ViewPropertyAnimator object, which can be used to animate
24776     * specific properties on this View.
24777     *
24778     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
24779     */
24780    public ViewPropertyAnimator animate() {
24781        if (mAnimator == null) {
24782            mAnimator = new ViewPropertyAnimator(this);
24783        }
24784        return mAnimator;
24785    }
24786
24787    /**
24788     * Sets the name of the View to be used to identify Views in Transitions.
24789     * Names should be unique in the View hierarchy.
24790     *
24791     * @param transitionName The name of the View to uniquely identify it for Transitions.
24792     */
24793    public final void setTransitionName(String transitionName) {
24794        mTransitionName = transitionName;
24795    }
24796
24797    /**
24798     * Returns the name of the View to be used to identify Views in Transitions.
24799     * Names should be unique in the View hierarchy.
24800     *
24801     * <p>This returns null if the View has not been given a name.</p>
24802     *
24803     * @return The name used of the View to be used to identify Views in Transitions or null
24804     * if no name has been given.
24805     */
24806    @ViewDebug.ExportedProperty
24807    public String getTransitionName() {
24808        return mTransitionName;
24809    }
24810
24811    /**
24812     * @hide
24813     */
24814    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24815        // Do nothing.
24816    }
24817
24818    /**
24819     * Interface definition for a callback to be invoked when a hardware key event is
24820     * dispatched to this view. The callback will be invoked before the key event is
24821     * given to the view. This is only useful for hardware keyboards; a software input
24822     * method has no obligation to trigger this listener.
24823     */
24824    public interface OnKeyListener {
24825        /**
24826         * Called when a hardware key is dispatched to a view. This allows listeners to
24827         * get a chance to respond before the target view.
24828         * <p>Key presses in software keyboards will generally NOT trigger this method,
24829         * although some may elect to do so in some situations. Do not assume a
24830         * software input method has to be key-based; even if it is, it may use key presses
24831         * in a different way than you expect, so there is no way to reliably catch soft
24832         * input key presses.
24833         *
24834         * @param v The view the key has been dispatched to.
24835         * @param keyCode The code for the physical key that was pressed
24836         * @param event The KeyEvent object containing full information about
24837         *        the event.
24838         * @return True if the listener has consumed the event, false otherwise.
24839         */
24840        boolean onKey(View v, int keyCode, KeyEvent event);
24841    }
24842
24843    /**
24844     * Interface definition for a callback to be invoked when a touch event is
24845     * dispatched to this view. The callback will be invoked before the touch
24846     * event is given to the view.
24847     */
24848    public interface OnTouchListener {
24849        /**
24850         * Called when a touch event is dispatched to a view. This allows listeners to
24851         * get a chance to respond before the target view.
24852         *
24853         * @param v The view the touch event has been dispatched to.
24854         * @param event The MotionEvent object containing full information about
24855         *        the event.
24856         * @return True if the listener has consumed the event, false otherwise.
24857         */
24858        boolean onTouch(View v, MotionEvent event);
24859    }
24860
24861    /**
24862     * Interface definition for a callback to be invoked when a hover event is
24863     * dispatched to this view. The callback will be invoked before the hover
24864     * event is given to the view.
24865     */
24866    public interface OnHoverListener {
24867        /**
24868         * Called when a hover event is dispatched to a view. This allows listeners to
24869         * get a chance to respond before the target view.
24870         *
24871         * @param v The view the hover event has been dispatched to.
24872         * @param event The MotionEvent object containing full information about
24873         *        the event.
24874         * @return True if the listener has consumed the event, false otherwise.
24875         */
24876        boolean onHover(View v, MotionEvent event);
24877    }
24878
24879    /**
24880     * Interface definition for a callback to be invoked when a generic motion event is
24881     * dispatched to this view. The callback will be invoked before the generic motion
24882     * event is given to the view.
24883     */
24884    public interface OnGenericMotionListener {
24885        /**
24886         * Called when a generic motion event is dispatched to a view. This allows listeners to
24887         * get a chance to respond before the target view.
24888         *
24889         * @param v The view the generic motion event has been dispatched to.
24890         * @param event The MotionEvent object containing full information about
24891         *        the event.
24892         * @return True if the listener has consumed the event, false otherwise.
24893         */
24894        boolean onGenericMotion(View v, MotionEvent event);
24895    }
24896
24897    /**
24898     * Interface definition for a callback to be invoked when a view has been clicked and held.
24899     */
24900    public interface OnLongClickListener {
24901        /**
24902         * Called when a view has been clicked and held.
24903         *
24904         * @param v The view that was clicked and held.
24905         *
24906         * @return true if the callback consumed the long click, false otherwise.
24907         */
24908        boolean onLongClick(View v);
24909    }
24910
24911    /**
24912     * Interface definition for a callback to be invoked when a drag is being dispatched
24913     * to this view.  The callback will be invoked before the hosting view's own
24914     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24915     * onDrag(event) behavior, it should return 'false' from this callback.
24916     *
24917     * <div class="special reference">
24918     * <h3>Developer Guides</h3>
24919     * <p>For a guide to implementing drag and drop features, read the
24920     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24921     * </div>
24922     */
24923    public interface OnDragListener {
24924        /**
24925         * Called when a drag event is dispatched to a view. This allows listeners
24926         * to get a chance to override base View behavior.
24927         *
24928         * @param v The View that received the drag event.
24929         * @param event The {@link android.view.DragEvent} object for the drag event.
24930         * @return {@code true} if the drag event was handled successfully, or {@code false}
24931         * if the drag event was not handled. Note that {@code false} will trigger the View
24932         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24933         */
24934        boolean onDrag(View v, DragEvent event);
24935    }
24936
24937    /**
24938     * Interface definition for a callback to be invoked when the focus state of
24939     * a view changed.
24940     */
24941    public interface OnFocusChangeListener {
24942        /**
24943         * Called when the focus state of a view has changed.
24944         *
24945         * @param v The view whose state has changed.
24946         * @param hasFocus The new focus state of v.
24947         */
24948        void onFocusChange(View v, boolean hasFocus);
24949    }
24950
24951    /**
24952     * Interface definition for a callback to be invoked when a view is clicked.
24953     */
24954    public interface OnClickListener {
24955        /**
24956         * Called when a view has been clicked.
24957         *
24958         * @param v The view that was clicked.
24959         */
24960        void onClick(View v);
24961    }
24962
24963    /**
24964     * Interface definition for a callback to be invoked when a view is context clicked.
24965     */
24966    public interface OnContextClickListener {
24967        /**
24968         * Called when a view is context clicked.
24969         *
24970         * @param v The view that has been context clicked.
24971         * @return true if the callback consumed the context click, false otherwise.
24972         */
24973        boolean onContextClick(View v);
24974    }
24975
24976    /**
24977     * Interface definition for a callback to be invoked when the context menu
24978     * for this view is being built.
24979     */
24980    public interface OnCreateContextMenuListener {
24981        /**
24982         * Called when the context menu for this view is being built. It is not
24983         * safe to hold onto the menu after this method returns.
24984         *
24985         * @param menu The context menu that is being built
24986         * @param v The view for which the context menu is being built
24987         * @param menuInfo Extra information about the item for which the
24988         *            context menu should be shown. This information will vary
24989         *            depending on the class of v.
24990         */
24991        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24992    }
24993
24994    /**
24995     * Interface definition for a callback to be invoked when the status bar changes
24996     * visibility.  This reports <strong>global</strong> changes to the system UI
24997     * state, not what the application is requesting.
24998     *
24999     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
25000     */
25001    public interface OnSystemUiVisibilityChangeListener {
25002        /**
25003         * Called when the status bar changes visibility because of a call to
25004         * {@link View#setSystemUiVisibility(int)}.
25005         *
25006         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
25007         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
25008         * This tells you the <strong>global</strong> state of these UI visibility
25009         * flags, not what your app is currently applying.
25010         */
25011        public void onSystemUiVisibilityChange(int visibility);
25012    }
25013
25014    /**
25015     * Interface definition for a callback to be invoked when this view is attached
25016     * or detached from its window.
25017     */
25018    public interface OnAttachStateChangeListener {
25019        /**
25020         * Called when the view is attached to a window.
25021         * @param v The view that was attached
25022         */
25023        public void onViewAttachedToWindow(View v);
25024        /**
25025         * Called when the view is detached from a window.
25026         * @param v The view that was detached
25027         */
25028        public void onViewDetachedFromWindow(View v);
25029    }
25030
25031    /**
25032     * Listener for applying window insets on a view in a custom way.
25033     *
25034     * <p>Apps may choose to implement this interface if they want to apply custom policy
25035     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
25036     * is set, its
25037     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
25038     * method will be called instead of the View's own
25039     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
25040     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
25041     * the View's normal behavior as part of its own.</p>
25042     */
25043    public interface OnApplyWindowInsetsListener {
25044        /**
25045         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
25046         * on a View, this listener method will be called instead of the view's own
25047         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
25048         *
25049         * @param v The view applying window insets
25050         * @param insets The insets to apply
25051         * @return The insets supplied, minus any insets that were consumed
25052         */
25053        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
25054    }
25055
25056    private final class UnsetPressedState implements Runnable {
25057        @Override
25058        public void run() {
25059            setPressed(false);
25060        }
25061    }
25062
25063    /**
25064     * When a view becomes invisible checks if autofill considers the view invisible too. This
25065     * happens after the regular removal operation to make sure the operation is finished by the
25066     * time this is called.
25067     */
25068    private static class VisibilityChangeForAutofillHandler extends Handler {
25069        private final AutofillManager mAfm;
25070        private final View mView;
25071
25072        private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
25073                @NonNull View view) {
25074            mAfm = afm;
25075            mView = view;
25076        }
25077
25078        @Override
25079        public void handleMessage(Message msg) {
25080            mAfm.notifyViewVisibilityChanged(mView, mView.isShown());
25081        }
25082    }
25083
25084    /**
25085     * Base class for derived classes that want to save and restore their own
25086     * state in {@link android.view.View#onSaveInstanceState()}.
25087     */
25088    public static class BaseSavedState extends AbsSavedState {
25089        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
25090        static final int IS_AUTOFILLED = 0b10;
25091        static final int AUTOFILL_ID = 0b100;
25092
25093        // Flags that describe what data in this state is valid
25094        int mSavedData;
25095        String mStartActivityRequestWhoSaved;
25096        boolean mIsAutofilled;
25097        int mAutofillViewId;
25098
25099        /**
25100         * Constructor used when reading from a parcel. Reads the state of the superclass.
25101         *
25102         * @param source parcel to read from
25103         */
25104        public BaseSavedState(Parcel source) {
25105            this(source, null);
25106        }
25107
25108        /**
25109         * Constructor used when reading from a parcel using a given class loader.
25110         * Reads the state of the superclass.
25111         *
25112         * @param source parcel to read from
25113         * @param loader ClassLoader to use for reading
25114         */
25115        public BaseSavedState(Parcel source, ClassLoader loader) {
25116            super(source, loader);
25117            mSavedData = source.readInt();
25118            mStartActivityRequestWhoSaved = source.readString();
25119            mIsAutofilled = source.readBoolean();
25120            mAutofillViewId = source.readInt();
25121        }
25122
25123        /**
25124         * Constructor called by derived classes when creating their SavedState objects
25125         *
25126         * @param superState The state of the superclass of this view
25127         */
25128        public BaseSavedState(Parcelable superState) {
25129            super(superState);
25130        }
25131
25132        @Override
25133        public void writeToParcel(Parcel out, int flags) {
25134            super.writeToParcel(out, flags);
25135
25136            out.writeInt(mSavedData);
25137            out.writeString(mStartActivityRequestWhoSaved);
25138            out.writeBoolean(mIsAutofilled);
25139            out.writeInt(mAutofillViewId);
25140        }
25141
25142        public static final Parcelable.Creator<BaseSavedState> CREATOR
25143                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
25144            @Override
25145            public BaseSavedState createFromParcel(Parcel in) {
25146                return new BaseSavedState(in);
25147            }
25148
25149            @Override
25150            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
25151                return new BaseSavedState(in, loader);
25152            }
25153
25154            @Override
25155            public BaseSavedState[] newArray(int size) {
25156                return new BaseSavedState[size];
25157            }
25158        };
25159    }
25160
25161    /**
25162     * A set of information given to a view when it is attached to its parent
25163     * window.
25164     */
25165    final static class AttachInfo {
25166        interface Callbacks {
25167            void playSoundEffect(int effectId);
25168            boolean performHapticFeedback(int effectId, boolean always);
25169        }
25170
25171        /**
25172         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
25173         * to a Handler. This class contains the target (View) to invalidate and
25174         * the coordinates of the dirty rectangle.
25175         *
25176         * For performance purposes, this class also implements a pool of up to
25177         * POOL_LIMIT objects that get reused. This reduces memory allocations
25178         * whenever possible.
25179         */
25180        static class InvalidateInfo {
25181            private static final int POOL_LIMIT = 10;
25182
25183            private static final SynchronizedPool<InvalidateInfo> sPool =
25184                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
25185
25186            View target;
25187
25188            int left;
25189            int top;
25190            int right;
25191            int bottom;
25192
25193            public static InvalidateInfo obtain() {
25194                InvalidateInfo instance = sPool.acquire();
25195                return (instance != null) ? instance : new InvalidateInfo();
25196            }
25197
25198            public void recycle() {
25199                target = null;
25200                sPool.release(this);
25201            }
25202        }
25203
25204        final IWindowSession mSession;
25205
25206        final IWindow mWindow;
25207
25208        final IBinder mWindowToken;
25209
25210        Display mDisplay;
25211
25212        final Callbacks mRootCallbacks;
25213
25214        IWindowId mIWindowId;
25215        WindowId mWindowId;
25216
25217        /**
25218         * The top view of the hierarchy.
25219         */
25220        View mRootView;
25221
25222        IBinder mPanelParentWindowToken;
25223
25224        boolean mHardwareAccelerated;
25225        boolean mHardwareAccelerationRequested;
25226        ThreadedRenderer mThreadedRenderer;
25227        List<RenderNode> mPendingAnimatingRenderNodes;
25228
25229        /**
25230         * The state of the display to which the window is attached, as reported
25231         * by {@link Display#getState()}.  Note that the display state constants
25232         * declared by {@link Display} do not exactly line up with the screen state
25233         * constants declared by {@link View} (there are more display states than
25234         * screen states).
25235         */
25236        int mDisplayState = Display.STATE_UNKNOWN;
25237
25238        /**
25239         * Scale factor used by the compatibility mode
25240         */
25241        float mApplicationScale;
25242
25243        /**
25244         * Indicates whether the application is in compatibility mode
25245         */
25246        boolean mScalingRequired;
25247
25248        /**
25249         * Left position of this view's window
25250         */
25251        int mWindowLeft;
25252
25253        /**
25254         * Top position of this view's window
25255         */
25256        int mWindowTop;
25257
25258        /**
25259         * Indicates whether views need to use 32-bit drawing caches
25260         */
25261        boolean mUse32BitDrawingCache;
25262
25263        /**
25264         * For windows that are full-screen but using insets to layout inside
25265         * of the screen areas, these are the current insets to appear inside
25266         * the overscan area of the display.
25267         */
25268        final Rect mOverscanInsets = new Rect();
25269
25270        /**
25271         * For windows that are full-screen but using insets to layout inside
25272         * of the screen decorations, these are the current insets for the
25273         * content of the window.
25274         */
25275        final Rect mContentInsets = new Rect();
25276
25277        /**
25278         * For windows that are full-screen but using insets to layout inside
25279         * of the screen decorations, these are the current insets for the
25280         * actual visible parts of the window.
25281         */
25282        final Rect mVisibleInsets = new Rect();
25283
25284        /**
25285         * For windows that are full-screen but using insets to layout inside
25286         * of the screen decorations, these are the current insets for the
25287         * stable system windows.
25288         */
25289        final Rect mStableInsets = new Rect();
25290
25291        /**
25292         * For windows that include areas that are not covered by real surface these are the outsets
25293         * for real surface.
25294         */
25295        final Rect mOutsets = new Rect();
25296
25297        /**
25298         * In multi-window we force show the navigation bar. Because we don't want that the surface
25299         * size changes in this mode, we instead have a flag whether the navigation bar size should
25300         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
25301         */
25302        boolean mAlwaysConsumeNavBar;
25303
25304        /**
25305         * The internal insets given by this window.  This value is
25306         * supplied by the client (through
25307         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
25308         * be given to the window manager when changed to be used in laying
25309         * out windows behind it.
25310         */
25311        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
25312                = new ViewTreeObserver.InternalInsetsInfo();
25313
25314        /**
25315         * Set to true when mGivenInternalInsets is non-empty.
25316         */
25317        boolean mHasNonEmptyGivenInternalInsets;
25318
25319        /**
25320         * All views in the window's hierarchy that serve as scroll containers,
25321         * used to determine if the window can be resized or must be panned
25322         * to adjust for a soft input area.
25323         */
25324        final ArrayList<View> mScrollContainers = new ArrayList<View>();
25325
25326        final KeyEvent.DispatcherState mKeyDispatchState
25327                = new KeyEvent.DispatcherState();
25328
25329        /**
25330         * Indicates whether the view's window currently has the focus.
25331         */
25332        boolean mHasWindowFocus;
25333
25334        /**
25335         * The current visibility of the window.
25336         */
25337        int mWindowVisibility;
25338
25339        /**
25340         * Indicates the time at which drawing started to occur.
25341         */
25342        long mDrawingTime;
25343
25344        /**
25345         * Indicates whether or not ignoring the DIRTY_MASK flags.
25346         */
25347        boolean mIgnoreDirtyState;
25348
25349        /**
25350         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
25351         * to avoid clearing that flag prematurely.
25352         */
25353        boolean mSetIgnoreDirtyState = false;
25354
25355        /**
25356         * Indicates whether the view's window is currently in touch mode.
25357         */
25358        boolean mInTouchMode;
25359
25360        /**
25361         * Indicates whether the view has requested unbuffered input dispatching for the current
25362         * event stream.
25363         */
25364        boolean mUnbufferedDispatchRequested;
25365
25366        /**
25367         * Indicates that ViewAncestor should trigger a global layout change
25368         * the next time it performs a traversal
25369         */
25370        boolean mRecomputeGlobalAttributes;
25371
25372        /**
25373         * Always report new attributes at next traversal.
25374         */
25375        boolean mForceReportNewAttributes;
25376
25377        /**
25378         * Set during a traveral if any views want to keep the screen on.
25379         */
25380        boolean mKeepScreenOn;
25381
25382        /**
25383         * Set during a traveral if the light center needs to be updated.
25384         */
25385        boolean mNeedsUpdateLightCenter;
25386
25387        /**
25388         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
25389         */
25390        int mSystemUiVisibility;
25391
25392        /**
25393         * Hack to force certain system UI visibility flags to be cleared.
25394         */
25395        int mDisabledSystemUiVisibility;
25396
25397        /**
25398         * Last global system UI visibility reported by the window manager.
25399         */
25400        int mGlobalSystemUiVisibility = -1;
25401
25402        /**
25403         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
25404         * attached.
25405         */
25406        boolean mHasSystemUiListeners;
25407
25408        /**
25409         * Set if the window has requested to extend into the overscan region
25410         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
25411         */
25412        boolean mOverscanRequested;
25413
25414        /**
25415         * Set if the visibility of any views has changed.
25416         */
25417        boolean mViewVisibilityChanged;
25418
25419        /**
25420         * Set to true if a view has been scrolled.
25421         */
25422        boolean mViewScrollChanged;
25423
25424        /**
25425         * Set to true if high contrast mode enabled
25426         */
25427        boolean mHighContrastText;
25428
25429        /**
25430         * Set to true if a pointer event is currently being handled.
25431         */
25432        boolean mHandlingPointerEvent;
25433
25434        /**
25435         * Global to the view hierarchy used as a temporary for dealing with
25436         * x/y points in the transparent region computations.
25437         */
25438        final int[] mTransparentLocation = new int[2];
25439
25440        /**
25441         * Global to the view hierarchy used as a temporary for dealing with
25442         * x/y points in the ViewGroup.invalidateChild implementation.
25443         */
25444        final int[] mInvalidateChildLocation = new int[2];
25445
25446        /**
25447         * Global to the view hierarchy used as a temporary for dealing with
25448         * computing absolute on-screen location.
25449         */
25450        final int[] mTmpLocation = new int[2];
25451
25452        /**
25453         * Global to the view hierarchy used as a temporary for dealing with
25454         * x/y location when view is transformed.
25455         */
25456        final float[] mTmpTransformLocation = new float[2];
25457
25458        /**
25459         * The view tree observer used to dispatch global events like
25460         * layout, pre-draw, touch mode change, etc.
25461         */
25462        final ViewTreeObserver mTreeObserver;
25463
25464        /**
25465         * A Canvas used by the view hierarchy to perform bitmap caching.
25466         */
25467        Canvas mCanvas;
25468
25469        /**
25470         * The view root impl.
25471         */
25472        final ViewRootImpl mViewRootImpl;
25473
25474        /**
25475         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
25476         * handler can be used to pump events in the UI events queue.
25477         */
25478        final Handler mHandler;
25479
25480        /**
25481         * Temporary for use in computing invalidate rectangles while
25482         * calling up the hierarchy.
25483         */
25484        final Rect mTmpInvalRect = new Rect();
25485
25486        /**
25487         * Temporary for use in computing hit areas with transformed views
25488         */
25489        final RectF mTmpTransformRect = new RectF();
25490
25491        /**
25492         * Temporary for use in computing hit areas with transformed views
25493         */
25494        final RectF mTmpTransformRect1 = new RectF();
25495
25496        /**
25497         * Temporary list of rectanges.
25498         */
25499        final List<RectF> mTmpRectList = new ArrayList<>();
25500
25501        /**
25502         * Temporary for use in transforming invalidation rect
25503         */
25504        final Matrix mTmpMatrix = new Matrix();
25505
25506        /**
25507         * Temporary for use in transforming invalidation rect
25508         */
25509        final Transformation mTmpTransformation = new Transformation();
25510
25511        /**
25512         * Temporary for use in querying outlines from OutlineProviders
25513         */
25514        final Outline mTmpOutline = new Outline();
25515
25516        /**
25517         * Temporary list for use in collecting focusable descendents of a view.
25518         */
25519        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
25520
25521        /**
25522         * The id of the window for accessibility purposes.
25523         */
25524        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
25525
25526        /**
25527         * Flags related to accessibility processing.
25528         *
25529         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
25530         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
25531         */
25532        int mAccessibilityFetchFlags;
25533
25534        /**
25535         * The drawable for highlighting accessibility focus.
25536         */
25537        Drawable mAccessibilityFocusDrawable;
25538
25539        /**
25540         * The drawable for highlighting autofilled views.
25541         *
25542         * @see #isAutofilled()
25543         */
25544        Drawable mAutofilledDrawable;
25545
25546        /**
25547         * Show where the margins, bounds and layout bounds are for each view.
25548         */
25549        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
25550
25551        /**
25552         * Point used to compute visible regions.
25553         */
25554        final Point mPoint = new Point();
25555
25556        /**
25557         * Used to track which View originated a requestLayout() call, used when
25558         * requestLayout() is called during layout.
25559         */
25560        View mViewRequestingLayout;
25561
25562        /**
25563         * Used to track views that need (at least) a partial relayout at their current size
25564         * during the next traversal.
25565         */
25566        List<View> mPartialLayoutViews = new ArrayList<>();
25567
25568        /**
25569         * Swapped with mPartialLayoutViews during layout to avoid concurrent
25570         * modification. Lazily assigned during ViewRootImpl layout.
25571         */
25572        List<View> mEmptyPartialLayoutViews;
25573
25574        /**
25575         * Used to track the identity of the current drag operation.
25576         */
25577        IBinder mDragToken;
25578
25579        /**
25580         * The drag shadow surface for the current drag operation.
25581         */
25582        public Surface mDragSurface;
25583
25584
25585        /**
25586         * The view that currently has a tooltip displayed.
25587         */
25588        View mTooltipHost;
25589
25590        /**
25591         * Creates a new set of attachment information with the specified
25592         * events handler and thread.
25593         *
25594         * @param handler the events handler the view must use
25595         */
25596        AttachInfo(IWindowSession session, IWindow window, Display display,
25597                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
25598                Context context) {
25599            mSession = session;
25600            mWindow = window;
25601            mWindowToken = window.asBinder();
25602            mDisplay = display;
25603            mViewRootImpl = viewRootImpl;
25604            mHandler = handler;
25605            mRootCallbacks = effectPlayer;
25606            mTreeObserver = new ViewTreeObserver(context);
25607        }
25608    }
25609
25610    /**
25611     * <p>ScrollabilityCache holds various fields used by a View when scrolling
25612     * is supported. This avoids keeping too many unused fields in most
25613     * instances of View.</p>
25614     */
25615    private static class ScrollabilityCache implements Runnable {
25616
25617        /**
25618         * Scrollbars are not visible
25619         */
25620        public static final int OFF = 0;
25621
25622        /**
25623         * Scrollbars are visible
25624         */
25625        public static final int ON = 1;
25626
25627        /**
25628         * Scrollbars are fading away
25629         */
25630        public static final int FADING = 2;
25631
25632        public boolean fadeScrollBars;
25633
25634        public int fadingEdgeLength;
25635        public int scrollBarDefaultDelayBeforeFade;
25636        public int scrollBarFadeDuration;
25637
25638        public int scrollBarSize;
25639        public int scrollBarMinTouchTarget;
25640        public ScrollBarDrawable scrollBar;
25641        public float[] interpolatorValues;
25642        public View host;
25643
25644        public final Paint paint;
25645        public final Matrix matrix;
25646        public Shader shader;
25647
25648        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
25649
25650        private static final float[] OPAQUE = { 255 };
25651        private static final float[] TRANSPARENT = { 0.0f };
25652
25653        /**
25654         * When fading should start. This time moves into the future every time
25655         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
25656         */
25657        public long fadeStartTime;
25658
25659
25660        /**
25661         * The current state of the scrollbars: ON, OFF, or FADING
25662         */
25663        public int state = OFF;
25664
25665        private int mLastColor;
25666
25667        public final Rect mScrollBarBounds = new Rect();
25668        public final Rect mScrollBarTouchBounds = new Rect();
25669
25670        public static final int NOT_DRAGGING = 0;
25671        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
25672        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
25673        public int mScrollBarDraggingState = NOT_DRAGGING;
25674
25675        public float mScrollBarDraggingPos = 0;
25676
25677        public ScrollabilityCache(ViewConfiguration configuration, View host) {
25678            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
25679            scrollBarSize = configuration.getScaledScrollBarSize();
25680            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
25681            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
25682            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
25683
25684            paint = new Paint();
25685            matrix = new Matrix();
25686            // use use a height of 1, and then wack the matrix each time we
25687            // actually use it.
25688            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25689            paint.setShader(shader);
25690            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25691
25692            this.host = host;
25693        }
25694
25695        public void setFadeColor(int color) {
25696            if (color != mLastColor) {
25697                mLastColor = color;
25698
25699                if (color != 0) {
25700                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
25701                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
25702                    paint.setShader(shader);
25703                    // Restore the default transfer mode (src_over)
25704                    paint.setXfermode(null);
25705                } else {
25706                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25707                    paint.setShader(shader);
25708                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25709                }
25710            }
25711        }
25712
25713        public void run() {
25714            long now = AnimationUtils.currentAnimationTimeMillis();
25715            if (now >= fadeStartTime) {
25716
25717                // the animation fades the scrollbars out by changing
25718                // the opacity (alpha) from fully opaque to fully
25719                // transparent
25720                int nextFrame = (int) now;
25721                int framesCount = 0;
25722
25723                Interpolator interpolator = scrollBarInterpolator;
25724
25725                // Start opaque
25726                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
25727
25728                // End transparent
25729                nextFrame += scrollBarFadeDuration;
25730                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
25731
25732                state = FADING;
25733
25734                // Kick off the fade animation
25735                host.invalidate(true);
25736            }
25737        }
25738    }
25739
25740    /**
25741     * Resuable callback for sending
25742     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
25743     */
25744    private class SendViewScrolledAccessibilityEvent implements Runnable {
25745        public volatile boolean mIsPending;
25746
25747        public void run() {
25748            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
25749            mIsPending = false;
25750        }
25751    }
25752
25753    /**
25754     * <p>
25755     * This class represents a delegate that can be registered in a {@link View}
25756     * to enhance accessibility support via composition rather via inheritance.
25757     * It is specifically targeted to widget developers that extend basic View
25758     * classes i.e. classes in package android.view, that would like their
25759     * applications to be backwards compatible.
25760     * </p>
25761     * <div class="special reference">
25762     * <h3>Developer Guides</h3>
25763     * <p>For more information about making applications accessible, read the
25764     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
25765     * developer guide.</p>
25766     * </div>
25767     * <p>
25768     * A scenario in which a developer would like to use an accessibility delegate
25769     * is overriding a method introduced in a later API version than the minimal API
25770     * version supported by the application. For example, the method
25771     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
25772     * in API version 4 when the accessibility APIs were first introduced. If a
25773     * developer would like his application to run on API version 4 devices (assuming
25774     * all other APIs used by the application are version 4 or lower) and take advantage
25775     * of this method, instead of overriding the method which would break the application's
25776     * backwards compatibility, he can override the corresponding method in this
25777     * delegate and register the delegate in the target View if the API version of
25778     * the system is high enough, i.e. the API version is the same as or higher than the API
25779     * version that introduced
25780     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
25781     * </p>
25782     * <p>
25783     * Here is an example implementation:
25784     * </p>
25785     * <code><pre><p>
25786     * if (Build.VERSION.SDK_INT >= 14) {
25787     *     // If the API version is equal of higher than the version in
25788     *     // which onInitializeAccessibilityNodeInfo was introduced we
25789     *     // register a delegate with a customized implementation.
25790     *     View view = findViewById(R.id.view_id);
25791     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
25792     *         public void onInitializeAccessibilityNodeInfo(View host,
25793     *                 AccessibilityNodeInfo info) {
25794     *             // Let the default implementation populate the info.
25795     *             super.onInitializeAccessibilityNodeInfo(host, info);
25796     *             // Set some other information.
25797     *             info.setEnabled(host.isEnabled());
25798     *         }
25799     *     });
25800     * }
25801     * </code></pre></p>
25802     * <p>
25803     * This delegate contains methods that correspond to the accessibility methods
25804     * in View. If a delegate has been specified the implementation in View hands
25805     * off handling to the corresponding method in this delegate. The default
25806     * implementation the delegate methods behaves exactly as the corresponding
25807     * method in View for the case of no accessibility delegate been set. Hence,
25808     * to customize the behavior of a View method, clients can override only the
25809     * corresponding delegate method without altering the behavior of the rest
25810     * accessibility related methods of the host view.
25811     * </p>
25812     * <p>
25813     * <strong>Note:</strong> On platform versions prior to
25814     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
25815     * views in the {@code android.widget.*} package are called <i>before</i>
25816     * host methods. This prevents certain properties such as class name from
25817     * being modified by overriding
25818     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
25819     * as any changes will be overwritten by the host class.
25820     * <p>
25821     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
25822     * methods are called <i>after</i> host methods, which all properties to be
25823     * modified without being overwritten by the host class.
25824     */
25825    public static class AccessibilityDelegate {
25826
25827        /**
25828         * Sends an accessibility event of the given type. If accessibility is not
25829         * enabled this method has no effect.
25830         * <p>
25831         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
25832         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
25833         * been set.
25834         * </p>
25835         *
25836         * @param host The View hosting the delegate.
25837         * @param eventType The type of the event to send.
25838         *
25839         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25840         */
25841        public void sendAccessibilityEvent(View host, int eventType) {
25842            host.sendAccessibilityEventInternal(eventType);
25843        }
25844
25845        /**
25846         * Performs the specified accessibility action on the view. For
25847         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25848         * <p>
25849         * The default implementation behaves as
25850         * {@link View#performAccessibilityAction(int, Bundle)
25851         *  View#performAccessibilityAction(int, Bundle)} for the case of
25852         *  no accessibility delegate been set.
25853         * </p>
25854         *
25855         * @param action The action to perform.
25856         * @return Whether the action was performed.
25857         *
25858         * @see View#performAccessibilityAction(int, Bundle)
25859         *      View#performAccessibilityAction(int, Bundle)
25860         */
25861        public boolean performAccessibilityAction(View host, int action, Bundle args) {
25862            return host.performAccessibilityActionInternal(action, args);
25863        }
25864
25865        /**
25866         * Sends an accessibility event. This method behaves exactly as
25867         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25868         * empty {@link AccessibilityEvent} and does not perform a check whether
25869         * accessibility is enabled.
25870         * <p>
25871         * The default implementation behaves as
25872         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25873         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25874         * the case of no accessibility delegate been set.
25875         * </p>
25876         *
25877         * @param host The View hosting the delegate.
25878         * @param event The event to send.
25879         *
25880         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25881         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25882         */
25883        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25884            host.sendAccessibilityEventUncheckedInternal(event);
25885        }
25886
25887        /**
25888         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25889         * to its children for adding their text content to the event.
25890         * <p>
25891         * The default implementation behaves as
25892         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25893         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25894         * the case of no accessibility delegate been set.
25895         * </p>
25896         *
25897         * @param host The View hosting the delegate.
25898         * @param event The event.
25899         * @return True if the event population was completed.
25900         *
25901         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25902         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25903         */
25904        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25905            return host.dispatchPopulateAccessibilityEventInternal(event);
25906        }
25907
25908        /**
25909         * Gives a chance to the host View to populate the accessibility event with its
25910         * text content.
25911         * <p>
25912         * The default implementation behaves as
25913         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25914         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25915         * the case of no accessibility delegate been set.
25916         * </p>
25917         *
25918         * @param host The View hosting the delegate.
25919         * @param event The accessibility event which to populate.
25920         *
25921         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25922         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25923         */
25924        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25925            host.onPopulateAccessibilityEventInternal(event);
25926        }
25927
25928        /**
25929         * Initializes an {@link AccessibilityEvent} with information about the
25930         * the host View which is the event source.
25931         * <p>
25932         * The default implementation behaves as
25933         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25934         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25935         * the case of no accessibility delegate been set.
25936         * </p>
25937         *
25938         * @param host The View hosting the delegate.
25939         * @param event The event to initialize.
25940         *
25941         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25942         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25943         */
25944        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25945            host.onInitializeAccessibilityEventInternal(event);
25946        }
25947
25948        /**
25949         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25950         * <p>
25951         * The default implementation behaves as
25952         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25953         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25954         * the case of no accessibility delegate been set.
25955         * </p>
25956         *
25957         * @param host The View hosting the delegate.
25958         * @param info The instance to initialize.
25959         *
25960         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25961         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25962         */
25963        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25964            host.onInitializeAccessibilityNodeInfoInternal(info);
25965        }
25966
25967        /**
25968         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25969         * additional data.
25970         * <p>
25971         * This method only needs to be implemented if the View offers to provide additional data.
25972         * </p>
25973         * <p>
25974         * The default implementation behaves as
25975         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
25976         * for the case where no accessibility delegate is set.
25977         * </p>
25978         *
25979         * @param host The View hosting the delegate. Never {@code null}.
25980         * @param info The info to which to add the extra data. Never {@code null}.
25981         * @param extraDataKey A key specifying the type of extra data to add to the info. The
25982         *                     extra data should be added to the {@link Bundle} returned by
25983         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25984         *                     {@code null}.
25985         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25986         *                  May be {@code null} if the if the service provided no arguments.
25987         *
25988         * @see AccessibilityNodeInfo#setExtraAvailableData
25989         */
25990        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25991                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25992                @Nullable Bundle arguments) {
25993            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25994        }
25995
25996        /**
25997         * Called when a child of the host View has requested sending an
25998         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25999         * to augment the event.
26000         * <p>
26001         * The default implementation behaves as
26002         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
26003         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
26004         * the case of no accessibility delegate been set.
26005         * </p>
26006         *
26007         * @param host The View hosting the delegate.
26008         * @param child The child which requests sending the event.
26009         * @param event The event to be sent.
26010         * @return True if the event should be sent
26011         *
26012         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
26013         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
26014         */
26015        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
26016                AccessibilityEvent event) {
26017            return host.onRequestSendAccessibilityEventInternal(child, event);
26018        }
26019
26020        /**
26021         * Gets the provider for managing a virtual view hierarchy rooted at this View
26022         * and reported to {@link android.accessibilityservice.AccessibilityService}s
26023         * that explore the window content.
26024         * <p>
26025         * The default implementation behaves as
26026         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
26027         * the case of no accessibility delegate been set.
26028         * </p>
26029         *
26030         * @return The provider.
26031         *
26032         * @see AccessibilityNodeProvider
26033         */
26034        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
26035            return null;
26036        }
26037
26038        /**
26039         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
26040         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
26041         * This method is responsible for obtaining an accessibility node info from a
26042         * pool of reusable instances and calling
26043         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
26044         * view to initialize the former.
26045         * <p>
26046         * <strong>Note:</strong> The client is responsible for recycling the obtained
26047         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
26048         * creation.
26049         * </p>
26050         * <p>
26051         * The default implementation behaves as
26052         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
26053         * the case of no accessibility delegate been set.
26054         * </p>
26055         * @return A populated {@link AccessibilityNodeInfo}.
26056         *
26057         * @see AccessibilityNodeInfo
26058         *
26059         * @hide
26060         */
26061        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
26062            return host.createAccessibilityNodeInfoInternal();
26063        }
26064    }
26065
26066    private static class MatchIdPredicate implements Predicate<View> {
26067        public int mId;
26068
26069        @Override
26070        public boolean test(View view) {
26071            return (view.mID == mId);
26072        }
26073    }
26074
26075    private static class MatchLabelForPredicate implements Predicate<View> {
26076        private int mLabeledId;
26077
26078        @Override
26079        public boolean test(View view) {
26080            return (view.mLabelForId == mLabeledId);
26081        }
26082    }
26083
26084    /**
26085     * Dump all private flags in readable format, useful for documentation and
26086     * sanity checking.
26087     */
26088    private static void dumpFlags() {
26089        final HashMap<String, String> found = Maps.newHashMap();
26090        try {
26091            for (Field field : View.class.getDeclaredFields()) {
26092                final int modifiers = field.getModifiers();
26093                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
26094                    if (field.getType().equals(int.class)) {
26095                        final int value = field.getInt(null);
26096                        dumpFlag(found, field.getName(), value);
26097                    } else if (field.getType().equals(int[].class)) {
26098                        final int[] values = (int[]) field.get(null);
26099                        for (int i = 0; i < values.length; i++) {
26100                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
26101                        }
26102                    }
26103                }
26104            }
26105        } catch (IllegalAccessException e) {
26106            throw new RuntimeException(e);
26107        }
26108
26109        final ArrayList<String> keys = Lists.newArrayList();
26110        keys.addAll(found.keySet());
26111        Collections.sort(keys);
26112        for (String key : keys) {
26113            Log.d(VIEW_LOG_TAG, found.get(key));
26114        }
26115    }
26116
26117    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
26118        // Sort flags by prefix, then by bits, always keeping unique keys
26119        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
26120        final int prefix = name.indexOf('_');
26121        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
26122        final String output = bits + " " + name;
26123        found.put(key, output);
26124    }
26125
26126    /** {@hide} */
26127    public void encode(@NonNull ViewHierarchyEncoder stream) {
26128        stream.beginObject(this);
26129        encodeProperties(stream);
26130        stream.endObject();
26131    }
26132
26133    /** {@hide} */
26134    @CallSuper
26135    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
26136        Object resolveId = ViewDebug.resolveId(getContext(), mID);
26137        if (resolveId instanceof String) {
26138            stream.addProperty("id", (String) resolveId);
26139        } else {
26140            stream.addProperty("id", mID);
26141        }
26142
26143        stream.addProperty("misc:transformation.alpha",
26144                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
26145        stream.addProperty("misc:transitionName", getTransitionName());
26146
26147        // layout
26148        stream.addProperty("layout:left", mLeft);
26149        stream.addProperty("layout:right", mRight);
26150        stream.addProperty("layout:top", mTop);
26151        stream.addProperty("layout:bottom", mBottom);
26152        stream.addProperty("layout:width", getWidth());
26153        stream.addProperty("layout:height", getHeight());
26154        stream.addProperty("layout:layoutDirection", getLayoutDirection());
26155        stream.addProperty("layout:layoutRtl", isLayoutRtl());
26156        stream.addProperty("layout:hasTransientState", hasTransientState());
26157        stream.addProperty("layout:baseline", getBaseline());
26158
26159        // layout params
26160        ViewGroup.LayoutParams layoutParams = getLayoutParams();
26161        if (layoutParams != null) {
26162            stream.addPropertyKey("layoutParams");
26163            layoutParams.encode(stream);
26164        }
26165
26166        // scrolling
26167        stream.addProperty("scrolling:scrollX", mScrollX);
26168        stream.addProperty("scrolling:scrollY", mScrollY);
26169
26170        // padding
26171        stream.addProperty("padding:paddingLeft", mPaddingLeft);
26172        stream.addProperty("padding:paddingRight", mPaddingRight);
26173        stream.addProperty("padding:paddingTop", mPaddingTop);
26174        stream.addProperty("padding:paddingBottom", mPaddingBottom);
26175        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
26176        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
26177        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
26178        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
26179        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
26180
26181        // measurement
26182        stream.addProperty("measurement:minHeight", mMinHeight);
26183        stream.addProperty("measurement:minWidth", mMinWidth);
26184        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
26185        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
26186
26187        // drawing
26188        stream.addProperty("drawing:elevation", getElevation());
26189        stream.addProperty("drawing:translationX", getTranslationX());
26190        stream.addProperty("drawing:translationY", getTranslationY());
26191        stream.addProperty("drawing:translationZ", getTranslationZ());
26192        stream.addProperty("drawing:rotation", getRotation());
26193        stream.addProperty("drawing:rotationX", getRotationX());
26194        stream.addProperty("drawing:rotationY", getRotationY());
26195        stream.addProperty("drawing:scaleX", getScaleX());
26196        stream.addProperty("drawing:scaleY", getScaleY());
26197        stream.addProperty("drawing:pivotX", getPivotX());
26198        stream.addProperty("drawing:pivotY", getPivotY());
26199        stream.addProperty("drawing:opaque", isOpaque());
26200        stream.addProperty("drawing:alpha", getAlpha());
26201        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
26202        stream.addProperty("drawing:shadow", hasShadow());
26203        stream.addProperty("drawing:solidColor", getSolidColor());
26204        stream.addProperty("drawing:layerType", mLayerType);
26205        stream.addProperty("drawing:willNotDraw", willNotDraw());
26206        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
26207        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
26208        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
26209        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
26210
26211        // focus
26212        stream.addProperty("focus:hasFocus", hasFocus());
26213        stream.addProperty("focus:isFocused", isFocused());
26214        stream.addProperty("focus:focusable", getFocusable());
26215        stream.addProperty("focus:isFocusable", isFocusable());
26216        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
26217
26218        stream.addProperty("misc:clickable", isClickable());
26219        stream.addProperty("misc:pressed", isPressed());
26220        stream.addProperty("misc:selected", isSelected());
26221        stream.addProperty("misc:touchMode", isInTouchMode());
26222        stream.addProperty("misc:hovered", isHovered());
26223        stream.addProperty("misc:activated", isActivated());
26224
26225        stream.addProperty("misc:visibility", getVisibility());
26226        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
26227        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
26228
26229        stream.addProperty("misc:enabled", isEnabled());
26230        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
26231        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
26232
26233        // theme attributes
26234        Resources.Theme theme = getContext().getTheme();
26235        if (theme != null) {
26236            stream.addPropertyKey("theme");
26237            theme.encode(stream);
26238        }
26239
26240        // view attribute information
26241        int n = mAttributes != null ? mAttributes.length : 0;
26242        stream.addProperty("meta:__attrCount__", n/2);
26243        for (int i = 0; i < n; i += 2) {
26244            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
26245        }
26246
26247        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
26248
26249        // text
26250        stream.addProperty("text:textDirection", getTextDirection());
26251        stream.addProperty("text:textAlignment", getTextAlignment());
26252
26253        // accessibility
26254        CharSequence contentDescription = getContentDescription();
26255        stream.addProperty("accessibility:contentDescription",
26256                contentDescription == null ? "" : contentDescription.toString());
26257        stream.addProperty("accessibility:labelFor", getLabelFor());
26258        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
26259    }
26260
26261    /**
26262     * Determine if this view is rendered on a round wearable device and is the main view
26263     * on the screen.
26264     */
26265    boolean shouldDrawRoundScrollbar() {
26266        if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) {
26267            return false;
26268        }
26269
26270        final View rootView = getRootView();
26271        final WindowInsets insets = getRootWindowInsets();
26272
26273        int height = getHeight();
26274        int width = getWidth();
26275        int displayHeight = rootView.getHeight();
26276        int displayWidth = rootView.getWidth();
26277
26278        if (height != displayHeight || width != displayWidth) {
26279            return false;
26280        }
26281
26282        getLocationInWindow(mAttachInfo.mTmpLocation);
26283        return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft()
26284                && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop();
26285    }
26286
26287    /**
26288     * Sets the tooltip text which will be displayed in a small popup next to the view.
26289     * <p>
26290     * The tooltip will be displayed:
26291     * <ul>
26292     * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context
26293     * menu). </li>
26294     * <li>On hover, after a brief delay since the pointer has stopped moving </li>
26295     * </ul>
26296     * <p>
26297     * <strong>Note:</strong> Do not override this method, as it will have no
26298     * effect on the text displayed in the tooltip.
26299     *
26300     * @param tooltipText the tooltip text, or null if no tooltip is required
26301     * @see #getTooltipText()
26302     * @attr ref android.R.styleable#View_tooltipText
26303     */
26304    public void setTooltipText(@Nullable CharSequence tooltipText) {
26305        if (TextUtils.isEmpty(tooltipText)) {
26306            setFlags(0, TOOLTIP);
26307            hideTooltip();
26308            mTooltipInfo = null;
26309        } else {
26310            setFlags(TOOLTIP, TOOLTIP);
26311            if (mTooltipInfo == null) {
26312                mTooltipInfo = new TooltipInfo();
26313                mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip;
26314                mTooltipInfo.mHideTooltipRunnable = this::hideTooltip;
26315            }
26316            mTooltipInfo.mTooltipText = tooltipText;
26317        }
26318    }
26319
26320    /**
26321     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
26322     */
26323    public void setTooltip(@Nullable CharSequence tooltipText) {
26324        setTooltipText(tooltipText);
26325    }
26326
26327    /**
26328     * Returns the view's tooltip text.
26329     *
26330     * <strong>Note:</strong> Do not override this method, as it will have no
26331     * effect on the text displayed in the tooltip. You must call
26332     * {@link #setTooltipText(CharSequence)} to modify the tooltip text.
26333     *
26334     * @return the tooltip text
26335     * @see #setTooltipText(CharSequence)
26336     * @attr ref android.R.styleable#View_tooltipText
26337     */
26338    @Nullable
26339    public CharSequence getTooltipText() {
26340        return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null;
26341    }
26342
26343    /**
26344     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
26345     */
26346    @Nullable
26347    public CharSequence getTooltip() {
26348        return getTooltipText();
26349    }
26350
26351    private boolean showTooltip(int x, int y, boolean fromLongClick) {
26352        if (mAttachInfo == null || mTooltipInfo == null) {
26353            return false;
26354        }
26355        if ((mViewFlags & ENABLED_MASK) != ENABLED) {
26356            return false;
26357        }
26358        if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) {
26359            return false;
26360        }
26361        hideTooltip();
26362        mTooltipInfo.mTooltipFromLongClick = fromLongClick;
26363        mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext());
26364        final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN;
26365        mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText);
26366        mAttachInfo.mTooltipHost = this;
26367        return true;
26368    }
26369
26370    void hideTooltip() {
26371        if (mTooltipInfo == null) {
26372            return;
26373        }
26374        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26375        if (mTooltipInfo.mTooltipPopup == null) {
26376            return;
26377        }
26378        mTooltipInfo.mTooltipPopup.hide();
26379        mTooltipInfo.mTooltipPopup = null;
26380        mTooltipInfo.mTooltipFromLongClick = false;
26381        if (mAttachInfo != null) {
26382            mAttachInfo.mTooltipHost = null;
26383        }
26384    }
26385
26386    private boolean showLongClickTooltip(int x, int y) {
26387        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26388        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26389        return showTooltip(x, y, true);
26390    }
26391
26392    private void showHoverTooltip() {
26393        showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false);
26394    }
26395
26396    boolean dispatchTooltipHoverEvent(MotionEvent event) {
26397        if (mTooltipInfo == null) {
26398            return false;
26399        }
26400        switch(event.getAction()) {
26401            case MotionEvent.ACTION_HOVER_MOVE:
26402                if ((mViewFlags & TOOLTIP) != TOOLTIP || (mViewFlags & ENABLED_MASK) != ENABLED) {
26403                    break;
26404                }
26405                if (!mTooltipInfo.mTooltipFromLongClick) {
26406                    if (mTooltipInfo.mTooltipPopup == null) {
26407                        // Schedule showing the tooltip after a timeout.
26408                        mTooltipInfo.mAnchorX = (int) event.getX();
26409                        mTooltipInfo.mAnchorY = (int) event.getY();
26410                        removeCallbacks(mTooltipInfo.mShowTooltipRunnable);
26411                        postDelayed(mTooltipInfo.mShowTooltipRunnable,
26412                                ViewConfiguration.getHoverTooltipShowTimeout());
26413                    }
26414
26415                    // Hide hover-triggered tooltip after a period of inactivity.
26416                    // Match the timeout used by NativeInputManager to hide the mouse pointer
26417                    // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set).
26418                    final int timeout;
26419                    if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE)
26420                            == SYSTEM_UI_FLAG_LOW_PROFILE) {
26421                        timeout = ViewConfiguration.getHoverTooltipHideShortTimeout();
26422                    } else {
26423                        timeout = ViewConfiguration.getHoverTooltipHideTimeout();
26424                    }
26425                    removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26426                    postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout);
26427                }
26428                return true;
26429
26430            case MotionEvent.ACTION_HOVER_EXIT:
26431                if (!mTooltipInfo.mTooltipFromLongClick) {
26432                    hideTooltip();
26433                }
26434                break;
26435        }
26436        return false;
26437    }
26438
26439    void handleTooltipKey(KeyEvent event) {
26440        switch (event.getAction()) {
26441            case KeyEvent.ACTION_DOWN:
26442                if (event.getRepeatCount() == 0) {
26443                    hideTooltip();
26444                }
26445                break;
26446
26447            case KeyEvent.ACTION_UP:
26448                handleTooltipUp();
26449                break;
26450        }
26451    }
26452
26453    private void handleTooltipUp() {
26454        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26455            return;
26456        }
26457        removeCallbacks(mTooltipInfo.mHideTooltipRunnable);
26458        postDelayed(mTooltipInfo.mHideTooltipRunnable,
26459                ViewConfiguration.getLongPressTooltipHideTimeout());
26460    }
26461
26462    private int getFocusableAttribute(TypedArray attributes) {
26463        TypedValue val = new TypedValue();
26464        if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) {
26465            if (val.type == TypedValue.TYPE_INT_BOOLEAN) {
26466                return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE);
26467            } else {
26468                return val.data;
26469            }
26470        } else {
26471            return FOCUSABLE_AUTO;
26472        }
26473    }
26474
26475    /**
26476     * @return The content view of the tooltip popup currently being shown, or null if the tooltip
26477     * is not showing.
26478     * @hide
26479     */
26480    @TestApi
26481    public View getTooltipView() {
26482        if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) {
26483            return null;
26484        }
26485        return mTooltipInfo.mTooltipPopup.getContentView();
26486    }
26487}
26488