View.java revision 353d397d17c2224540cfe7fa4e33a1b0b4d3490f
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.Collection;
131import java.util.Collections;
132import java.util.HashMap;
133import java.util.List;
134import java.util.Locale;
135import java.util.Map;
136import java.util.concurrent.CopyOnWriteArrayList;
137import java.util.concurrent.atomic.AtomicInteger;
138import java.util.function.Predicate;
139
140/**
141 * <p>
142 * This class represents the basic building block for user interface components. A View
143 * occupies a rectangular area on the screen and is responsible for drawing and
144 * event handling. View is the base class for <em>widgets</em>, which are
145 * used to create interactive UI components (buttons, text fields, etc.). The
146 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
147 * are invisible containers that hold other Views (or other ViewGroups) and define
148 * their layout properties.
149 * </p>
150 *
151 * <div class="special reference">
152 * <h3>Developer Guides</h3>
153 * <p>For information about using this class to develop your application's user interface,
154 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
155 * </div>
156 *
157 * <a name="Using"></a>
158 * <h3>Using Views</h3>
159 * <p>
160 * All of the views in a window are arranged in a single tree. You can add views
161 * either from code or by specifying a tree of views in one or more XML layout
162 * files. There are many specialized subclasses of views that act as controls or
163 * are capable of displaying text, images, or other content.
164 * </p>
165 * <p>
166 * Once you have created a tree of views, there are typically a few types of
167 * common operations you may wish to perform:
168 * <ul>
169 * <li><strong>Set properties:</strong> for example setting the text of a
170 * {@link android.widget.TextView}. The available properties and the methods
171 * that set them will vary among the different subclasses of views. Note that
172 * properties that are known at build time can be set in the XML layout
173 * files.</li>
174 * <li><strong>Set focus:</strong> The framework will handle moving focus in
175 * response to user input. To force focus to a specific view, call
176 * {@link #requestFocus}.</li>
177 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
178 * that will be notified when something interesting happens to the view. For
179 * example, all views will let you set a listener to be notified when the view
180 * gains or loses focus. You can register such a listener using
181 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
182 * Other view subclasses offer more specialized listeners. For example, a Button
183 * exposes a listener to notify clients when the button is clicked.</li>
184 * <li><strong>Set visibility:</strong> You can hide or show views using
185 * {@link #setVisibility(int)}.</li>
186 * </ul>
187 * </p>
188 * <p><em>
189 * Note: The Android framework is responsible for measuring, laying out and
190 * drawing views. You should not call methods that perform these actions on
191 * views yourself unless you are actually implementing a
192 * {@link android.view.ViewGroup}.
193 * </em></p>
194 *
195 * <a name="Lifecycle"></a>
196 * <h3>Implementing a Custom View</h3>
197 *
198 * <p>
199 * To implement a custom view, you will usually begin by providing overrides for
200 * some of the standard methods that the framework calls on all views. You do
201 * not need to override all of these methods. In fact, you can start by just
202 * overriding {@link #onDraw(android.graphics.Canvas)}.
203 * <table border="2" width="85%" align="center" cellpadding="5">
204 *     <thead>
205 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
206 *     </thead>
207 *
208 *     <tbody>
209 *     <tr>
210 *         <td rowspan="2">Creation</td>
211 *         <td>Constructors</td>
212 *         <td>There is a form of the constructor that are called when the view
213 *         is created from code and a form that is called when the view is
214 *         inflated from a layout file. The second form should parse and apply
215 *         any attributes defined in the layout file.
216 *         </td>
217 *     </tr>
218 *     <tr>
219 *         <td><code>{@link #onFinishInflate()}</code></td>
220 *         <td>Called after a view and all of its children has been inflated
221 *         from XML.</td>
222 *     </tr>
223 *
224 *     <tr>
225 *         <td rowspan="3">Layout</td>
226 *         <td><code>{@link #onMeasure(int, int)}</code></td>
227 *         <td>Called to determine the size requirements for this view and all
228 *         of its children.
229 *         </td>
230 *     </tr>
231 *     <tr>
232 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
233 *         <td>Called when this view should assign a size and position to all
234 *         of its children.
235 *         </td>
236 *     </tr>
237 *     <tr>
238 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
239 *         <td>Called when the size of this view has changed.
240 *         </td>
241 *     </tr>
242 *
243 *     <tr>
244 *         <td>Drawing</td>
245 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
246 *         <td>Called when the view should render its content.
247 *         </td>
248 *     </tr>
249 *
250 *     <tr>
251 *         <td rowspan="4">Event processing</td>
252 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
253 *         <td>Called when a new hardware key event occurs.
254 *         </td>
255 *     </tr>
256 *     <tr>
257 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
258 *         <td>Called when a hardware key up event occurs.
259 *         </td>
260 *     </tr>
261 *     <tr>
262 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
263 *         <td>Called when a trackball motion event occurs.
264 *         </td>
265 *     </tr>
266 *     <tr>
267 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
268 *         <td>Called when a touch screen motion event occurs.
269 *         </td>
270 *     </tr>
271 *
272 *     <tr>
273 *         <td rowspan="2">Focus</td>
274 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
275 *         <td>Called when the view gains or loses focus.
276 *         </td>
277 *     </tr>
278 *
279 *     <tr>
280 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
281 *         <td>Called when the window containing the view gains or loses focus.
282 *         </td>
283 *     </tr>
284 *
285 *     <tr>
286 *         <td rowspan="3">Attaching</td>
287 *         <td><code>{@link #onAttachedToWindow()}</code></td>
288 *         <td>Called when the view is attached to a window.
289 *         </td>
290 *     </tr>
291 *
292 *     <tr>
293 *         <td><code>{@link #onDetachedFromWindow}</code></td>
294 *         <td>Called when the view is detached from its window.
295 *         </td>
296 *     </tr>
297 *
298 *     <tr>
299 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
300 *         <td>Called when the visibility of the window containing the view
301 *         has changed.
302 *         </td>
303 *     </tr>
304 *     </tbody>
305 *
306 * </table>
307 * </p>
308 *
309 * <a name="IDs"></a>
310 * <h3>IDs</h3>
311 * Views may have an integer id associated with them. These ids are typically
312 * assigned in the layout XML files, and are used to find specific views within
313 * the view tree. A common pattern is to:
314 * <ul>
315 * <li>Define a Button in the layout file and assign it a unique ID.
316 * <pre>
317 * &lt;Button
318 *     android:id="@+id/my_button"
319 *     android:layout_width="wrap_content"
320 *     android:layout_height="wrap_content"
321 *     android:text="@string/my_button_text"/&gt;
322 * </pre></li>
323 * <li>From the onCreate method of an Activity, find the Button
324 * <pre class="prettyprint">
325 *      Button myButton = findViewById(R.id.my_button);
326 * </pre></li>
327 * </ul>
328 * <p>
329 * View IDs need not be unique throughout the tree, but it is good practice to
330 * ensure that they are at least unique within the part of the tree you are
331 * searching.
332 * </p>
333 *
334 * <a name="Position"></a>
335 * <h3>Position</h3>
336 * <p>
337 * The geometry of a view is that of a rectangle. A view has a location,
338 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
339 * two dimensions, expressed as a width and a height. The unit for location
340 * and dimensions is the pixel.
341 * </p>
342 *
343 * <p>
344 * It is possible to retrieve the location of a view by invoking the methods
345 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
346 * coordinate of the rectangle representing the view. The latter returns the
347 * top, or Y, coordinate of the rectangle representing the view. These methods
348 * both return the location of the view relative to its parent. For instance,
349 * when getLeft() returns 20, that means the view is located 20 pixels to the
350 * right of the left edge of its direct parent.
351 * </p>
352 *
353 * <p>
354 * In addition, several convenience methods are offered to avoid unnecessary
355 * computations, namely {@link #getRight()} and {@link #getBottom()}.
356 * These methods return the coordinates of the right and bottom edges of the
357 * rectangle representing the view. For instance, calling {@link #getRight()}
358 * is similar to the following computation: <code>getLeft() + getWidth()</code>
359 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
360 * </p>
361 *
362 * <a name="SizePaddingMargins"></a>
363 * <h3>Size, padding and margins</h3>
364 * <p>
365 * The size of a view is expressed with a width and a height. A view actually
366 * possess two pairs of width and height values.
367 * </p>
368 *
369 * <p>
370 * The first pair is known as <em>measured width</em> and
371 * <em>measured height</em>. These dimensions define how big a view wants to be
372 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
373 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
374 * and {@link #getMeasuredHeight()}.
375 * </p>
376 *
377 * <p>
378 * The second pair is simply known as <em>width</em> and <em>height</em>, or
379 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
380 * dimensions define the actual size of the view on screen, at drawing time and
381 * after layout. These values may, but do not have to, be different from the
382 * measured width and height. The width and height can be obtained by calling
383 * {@link #getWidth()} and {@link #getHeight()}.
384 * </p>
385 *
386 * <p>
387 * To measure its dimensions, a view takes into account its padding. The padding
388 * is expressed in pixels for the left, top, right and bottom parts of the view.
389 * Padding can be used to offset the content of the view by a specific amount of
390 * pixels. For instance, a left padding of 2 will push the view's content by
391 * 2 pixels to the right of the left edge. Padding can be set using the
392 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
393 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
394 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
395 * {@link #getPaddingEnd()}.
396 * </p>
397 *
398 * <p>
399 * Even though a view can define a padding, it does not provide any support for
400 * margins. However, view groups provide such a support. Refer to
401 * {@link android.view.ViewGroup} and
402 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
403 * </p>
404 *
405 * <a name="Layout"></a>
406 * <h3>Layout</h3>
407 * <p>
408 * Layout is a two pass process: a measure pass and a layout pass. The measuring
409 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
410 * of the view tree. Each view pushes dimension specifications down the tree
411 * during the recursion. At the end of the measure pass, every view has stored
412 * its measurements. The second pass happens in
413 * {@link #layout(int,int,int,int)} and is also top-down. During
414 * this pass each parent is responsible for positioning all of its children
415 * using the sizes computed in the measure pass.
416 * </p>
417 *
418 * <p>
419 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
420 * {@link #getMeasuredHeight()} values must be set, along with those for all of
421 * that view's descendants. A view's measured width and measured height values
422 * must respect the constraints imposed by the view's parents. This guarantees
423 * that at the end of the measure pass, all parents accept all of their
424 * children's measurements. A parent view may call measure() more than once on
425 * its children. For example, the parent may measure each child once with
426 * unspecified dimensions to find out how big they want to be, then call
427 * measure() on them again with actual numbers if the sum of all the children's
428 * unconstrained sizes is too big or too small.
429 * </p>
430 *
431 * <p>
432 * The measure pass uses two classes to communicate dimensions. The
433 * {@link MeasureSpec} class is used by views to tell their parents how they
434 * want to be measured and positioned. The base LayoutParams class just
435 * describes how big the view wants to be for both width and height. For each
436 * dimension, it can specify one of:
437 * <ul>
438 * <li> an exact number
439 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
440 * (minus padding)
441 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
442 * enclose its content (plus padding).
443 * </ul>
444 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
445 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
446 * an X and Y value.
447 * </p>
448 *
449 * <p>
450 * MeasureSpecs are used to push requirements down the tree from parent to
451 * child. A MeasureSpec can be in one of three modes:
452 * <ul>
453 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
454 * of a child view. For example, a LinearLayout may call measure() on its child
455 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
456 * tall the child view wants to be given a width of 240 pixels.
457 * <li>EXACTLY: This is used by the parent to impose an exact size on the
458 * child. The child must use this size, and guarantee that all of its
459 * descendants will fit within this size.
460 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
461 * child. The child must guarantee that it and all of its descendants will fit
462 * within this size.
463 * </ul>
464 * </p>
465 *
466 * <p>
467 * To initiate a layout, call {@link #requestLayout}. This method is typically
468 * called by a view on itself when it believes that is can no longer fit within
469 * its current bounds.
470 * </p>
471 *
472 * <a name="Drawing"></a>
473 * <h3>Drawing</h3>
474 * <p>
475 * Drawing is handled by walking the tree and recording the drawing commands of
476 * any View that needs to update. After this, the drawing commands of the
477 * entire tree are issued to screen, clipped to the newly damaged area.
478 * </p>
479 *
480 * <p>
481 * The tree is largely recorded and drawn in order, with parents drawn before
482 * (i.e., behind) their children, with siblings drawn in the order they appear
483 * in the tree. If you set a background drawable for a View, then the View will
484 * draw it before calling back to its <code>onDraw()</code> method. The child
485 * drawing order can be overridden with
486 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
487 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
488 * </p>
489 *
490 * <p>
491 * To force a view to draw, call {@link #invalidate()}.
492 * </p>
493 *
494 * <a name="EventHandlingThreading"></a>
495 * <h3>Event Handling and Threading</h3>
496 * <p>
497 * The basic cycle of a view is as follows:
498 * <ol>
499 * <li>An event comes in and is dispatched to the appropriate view. The view
500 * handles the event and notifies any listeners.</li>
501 * <li>If in the course of processing the event, the view's bounds may need
502 * to be changed, the view will call {@link #requestLayout()}.</li>
503 * <li>Similarly, if in the course of processing the event the view's appearance
504 * may need to be changed, the view will call {@link #invalidate()}.</li>
505 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
506 * the framework will take care of measuring, laying out, and drawing the tree
507 * as appropriate.</li>
508 * </ol>
509 * </p>
510 *
511 * <p><em>Note: The entire view tree is single threaded. You must always be on
512 * the UI thread when calling any method on any view.</em>
513 * If you are doing work on other threads and want to update the state of a view
514 * from that thread, you should use a {@link Handler}.
515 * </p>
516 *
517 * <a name="FocusHandling"></a>
518 * <h3>Focus Handling</h3>
519 * <p>
520 * The framework will handle routine focus movement in response to user input.
521 * This includes changing the focus as views are removed or hidden, or as new
522 * views become available. Views indicate their willingness to take focus
523 * through the {@link #isFocusable} method. To change whether a view can take
524 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
525 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
526 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
527 * </p>
528 * <p>
529 * Focus movement is based on an algorithm which finds the nearest neighbor in a
530 * given direction. In rare cases, the default algorithm may not match the
531 * intended behavior of the developer. In these situations, you can provide
532 * explicit overrides by using these XML attributes in the layout file:
533 * <pre>
534 * nextFocusDown
535 * nextFocusLeft
536 * nextFocusRight
537 * nextFocusUp
538 * </pre>
539 * </p>
540 *
541 *
542 * <p>
543 * To get a particular view to take focus, call {@link #requestFocus()}.
544 * </p>
545 *
546 * <a name="TouchMode"></a>
547 * <h3>Touch Mode</h3>
548 * <p>
549 * When a user is navigating a user interface via directional keys such as a D-pad, it is
550 * necessary to give focus to actionable items such as buttons so the user can see
551 * what will take input.  If the device has touch capabilities, however, and the user
552 * begins interacting with the interface by touching it, it is no longer necessary to
553 * always highlight, or give focus to, a particular view.  This motivates a mode
554 * for interaction named 'touch mode'.
555 * </p>
556 * <p>
557 * For a touch capable device, once the user touches the screen, the device
558 * will enter touch mode.  From this point onward, only views for which
559 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
560 * Other views that are touchable, like buttons, will not take focus when touched; they will
561 * only fire the on click listeners.
562 * </p>
563 * <p>
564 * Any time a user hits a directional key, such as a D-pad direction, the view device will
565 * exit touch mode, and find a view to take focus, so that the user may resume interacting
566 * with the user interface without touching the screen again.
567 * </p>
568 * <p>
569 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
570 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
571 * </p>
572 *
573 * <a name="Scrolling"></a>
574 * <h3>Scrolling</h3>
575 * <p>
576 * The framework provides basic support for views that wish to internally
577 * scroll their content. This includes keeping track of the X and Y scroll
578 * offset as well as mechanisms for drawing scrollbars. See
579 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
580 * {@link #awakenScrollBars()} for more details.
581 * </p>
582 *
583 * <a name="Tags"></a>
584 * <h3>Tags</h3>
585 * <p>
586 * Unlike IDs, tags are not used to identify views. Tags are essentially an
587 * extra piece of information that can be associated with a view. They are most
588 * often used as a convenience to store data related to views in the views
589 * themselves rather than by putting them in a separate structure.
590 * </p>
591 * <p>
592 * Tags may be specified with character sequence values in layout XML as either
593 * a single tag using the {@link android.R.styleable#View_tag android:tag}
594 * attribute or multiple tags using the {@code <tag>} child element:
595 * <pre>
596 *     &lt;View ...
597 *           android:tag="@string/mytag_value" /&gt;
598 *     &lt;View ...&gt;
599 *         &lt;tag android:id="@+id/mytag"
600 *              android:value="@string/mytag_value" /&gt;
601 *     &lt;/View>
602 * </pre>
603 * </p>
604 * <p>
605 * Tags may also be specified with arbitrary objects from code using
606 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
607 * </p>
608 *
609 * <a name="Themes"></a>
610 * <h3>Themes</h3>
611 * <p>
612 * By default, Views are created using the theme of the Context object supplied
613 * to their constructor; however, a different theme may be specified by using
614 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
615 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
616 * code.
617 * </p>
618 * <p>
619 * When the {@link android.R.styleable#View_theme android:theme} attribute is
620 * used in XML, the specified theme is applied on top of the inflation
621 * context's theme (see {@link LayoutInflater}) and used for the view itself as
622 * well as any child elements.
623 * </p>
624 * <p>
625 * In the following example, both views will be created using the Material dark
626 * color scheme; however, because an overlay theme is used which only defines a
627 * subset of attributes, the value of
628 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
629 * the inflation context's theme (e.g. the Activity theme) will be preserved.
630 * <pre>
631 *     &lt;LinearLayout
632 *             ...
633 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
634 *         &lt;View ...&gt;
635 *     &lt;/LinearLayout&gt;
636 * </pre>
637 * </p>
638 *
639 * <a name="Properties"></a>
640 * <h3>Properties</h3>
641 * <p>
642 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
643 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
644 * available both in the {@link Property} form as well as in similarly-named setter/getter
645 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
646 * be used to set persistent state associated with these rendering-related properties on the view.
647 * The properties and methods can also be used in conjunction with
648 * {@link android.animation.Animator Animator}-based animations, described more in the
649 * <a href="#Animation">Animation</a> section.
650 * </p>
651 *
652 * <a name="Animation"></a>
653 * <h3>Animation</h3>
654 * <p>
655 * Starting with Android 3.0, the preferred way of animating views is to use the
656 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
657 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
658 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
659 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
660 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
661 * makes animating these View properties particularly easy and efficient.
662 * </p>
663 * <p>
664 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
665 * You can attach an {@link Animation} object to a view using
666 * {@link #setAnimation(Animation)} or
667 * {@link #startAnimation(Animation)}. The animation can alter the scale,
668 * rotation, translation and alpha of a view over time. If the animation is
669 * attached to a view that has children, the animation will affect the entire
670 * subtree rooted by that node. When an animation is started, the framework will
671 * take care of redrawing the appropriate views until the animation completes.
672 * </p>
673 *
674 * <a name="Security"></a>
675 * <h3>Security</h3>
676 * <p>
677 * Sometimes it is essential that an application be able to verify that an action
678 * is being performed with the full knowledge and consent of the user, such as
679 * granting a permission request, making a purchase or clicking on an advertisement.
680 * Unfortunately, a malicious application could try to spoof the user into
681 * performing these actions, unaware, by concealing the intended purpose of the view.
682 * As a remedy, the framework offers a touch filtering mechanism that can be used to
683 * improve the security of views that provide access to sensitive functionality.
684 * </p><p>
685 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
686 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
687 * will discard touches that are received whenever the view's window is obscured by
688 * another visible window.  As a result, the view will not receive touches whenever a
689 * toast, dialog or other window appears above the view's window.
690 * </p><p>
691 * For more fine-grained control over security, consider overriding the
692 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
693 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
694 * </p>
695 *
696 * @attr ref android.R.styleable#View_alpha
697 * @attr ref android.R.styleable#View_background
698 * @attr ref android.R.styleable#View_clickable
699 * @attr ref android.R.styleable#View_contentDescription
700 * @attr ref android.R.styleable#View_drawingCacheQuality
701 * @attr ref android.R.styleable#View_duplicateParentState
702 * @attr ref android.R.styleable#View_id
703 * @attr ref android.R.styleable#View_requiresFadingEdge
704 * @attr ref android.R.styleable#View_fadeScrollbars
705 * @attr ref android.R.styleable#View_fadingEdgeLength
706 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
707 * @attr ref android.R.styleable#View_fitsSystemWindows
708 * @attr ref android.R.styleable#View_isScrollContainer
709 * @attr ref android.R.styleable#View_focusable
710 * @attr ref android.R.styleable#View_focusableInTouchMode
711 * @attr ref android.R.styleable#View_focusedByDefault
712 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
713 * @attr ref android.R.styleable#View_keepScreenOn
714 * @attr ref android.R.styleable#View_keyboardNavigationCluster
715 * @attr ref android.R.styleable#View_layerType
716 * @attr ref android.R.styleable#View_layoutDirection
717 * @attr ref android.R.styleable#View_longClickable
718 * @attr ref android.R.styleable#View_minHeight
719 * @attr ref android.R.styleable#View_minWidth
720 * @attr ref android.R.styleable#View_nextClusterForward
721 * @attr ref android.R.styleable#View_nextFocusDown
722 * @attr ref android.R.styleable#View_nextFocusLeft
723 * @attr ref android.R.styleable#View_nextFocusRight
724 * @attr ref android.R.styleable#View_nextFocusUp
725 * @attr ref android.R.styleable#View_onClick
726 * @attr ref android.R.styleable#View_padding
727 * @attr ref android.R.styleable#View_paddingHorizontal
728 * @attr ref android.R.styleable#View_paddingVertical
729 * @attr ref android.R.styleable#View_paddingBottom
730 * @attr ref android.R.styleable#View_paddingLeft
731 * @attr ref android.R.styleable#View_paddingRight
732 * @attr ref android.R.styleable#View_paddingTop
733 * @attr ref android.R.styleable#View_paddingStart
734 * @attr ref android.R.styleable#View_paddingEnd
735 * @attr ref android.R.styleable#View_saveEnabled
736 * @attr ref android.R.styleable#View_rotation
737 * @attr ref android.R.styleable#View_rotationX
738 * @attr ref android.R.styleable#View_rotationY
739 * @attr ref android.R.styleable#View_scaleX
740 * @attr ref android.R.styleable#View_scaleY
741 * @attr ref android.R.styleable#View_scrollX
742 * @attr ref android.R.styleable#View_scrollY
743 * @attr ref android.R.styleable#View_scrollbarSize
744 * @attr ref android.R.styleable#View_scrollbarStyle
745 * @attr ref android.R.styleable#View_scrollbars
746 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
747 * @attr ref android.R.styleable#View_scrollbarFadeDuration
748 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
749 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
750 * @attr ref android.R.styleable#View_scrollbarThumbVertical
751 * @attr ref android.R.styleable#View_scrollbarTrackVertical
752 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
753 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
754 * @attr ref android.R.styleable#View_stateListAnimator
755 * @attr ref android.R.styleable#View_transitionName
756 * @attr ref android.R.styleable#View_soundEffectsEnabled
757 * @attr ref android.R.styleable#View_tag
758 * @attr ref android.R.styleable#View_textAlignment
759 * @attr ref android.R.styleable#View_textDirection
760 * @attr ref android.R.styleable#View_transformPivotX
761 * @attr ref android.R.styleable#View_transformPivotY
762 * @attr ref android.R.styleable#View_translationX
763 * @attr ref android.R.styleable#View_translationY
764 * @attr ref android.R.styleable#View_translationZ
765 * @attr ref android.R.styleable#View_visibility
766 * @attr ref android.R.styleable#View_theme
767 *
768 * @see android.view.ViewGroup
769 */
770@UiThread
771public class View implements Drawable.Callback, KeyEvent.Callback,
772        AccessibilityEventSource {
773    private static final boolean DBG = false;
774
775    /** @hide */
776    public static boolean DEBUG_DRAW = false;
777
778    /**
779     * The logging tag used by this class with android.util.Log.
780     */
781    protected static final String VIEW_LOG_TAG = "View";
782
783    /**
784     * When set to true, apps will draw debugging information about their layouts.
785     *
786     * @hide
787     */
788    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
789
790    /**
791     * When set to true, this view will save its attribute data.
792     *
793     * @hide
794     */
795    public static boolean mDebugViewAttributes = false;
796
797    /**
798     * Used to mark a View that has no ID.
799     */
800    public static final int NO_ID = -1;
801
802    /**
803     * Last ID that is given to Views that are no part of activities.
804     *
805     * {@hide}
806     */
807    public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2;
808
809    /**
810     * Attribute to find the autofilled highlight
811     *
812     * @see #getAutofilledDrawable()
813     */
814    private static final int[] AUTOFILL_HIGHLIGHT_ATTR =
815            new int[]{android.R.attr.autofilledHighlight};
816
817    /**
818     * Signals that compatibility booleans have been initialized according to
819     * target SDK versions.
820     */
821    private static boolean sCompatibilityDone = false;
822
823    /**
824     * Use the old (broken) way of building MeasureSpecs.
825     */
826    private static boolean sUseBrokenMakeMeasureSpec = false;
827
828    /**
829     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
830     */
831    static boolean sUseZeroUnspecifiedMeasureSpec = false;
832
833    /**
834     * Ignore any optimizations using the measure cache.
835     */
836    private static boolean sIgnoreMeasureCache = false;
837
838    /**
839     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
840     */
841    private static boolean sAlwaysRemeasureExactly = false;
842
843    /**
844     * Relax constraints around whether setLayoutParams() must be called after
845     * modifying the layout params.
846     */
847    private static boolean sLayoutParamsAlwaysChanged = false;
848
849    /**
850     * Allow setForeground/setBackground to be called (and ignored) on a textureview,
851     * without throwing
852     */
853    static boolean sTextureViewIgnoresDrawableSetters = false;
854
855    /**
856     * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend
857     * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to
858     * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API
859     * check is implemented for backwards compatibility.
860     *
861     * {@hide}
862     */
863    protected static boolean sPreserveMarginParamsInLayoutParamConversion;
864
865    /**
866     * Prior to N, when drag enters into child of a view that has already received an
867     * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event.
868     * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned
869     * false from its event handler for these events.
870     * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its
871     * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent.
872     * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation.
873     */
874    static boolean sCascadedDragDrop;
875
876    /**
877     * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable
878     * to determine things like whether or not to permit item click events. We can't break
879     * apps that do this just because more things (clickable things) are now auto-focusable
880     * and they would get different results, so give old behavior to old apps.
881     */
882    static boolean sHasFocusableExcludeAutoFocusable;
883
884    /**
885     * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly
886     * made focusable by default. As a result, apps could (incorrectly) change the clickable
887     * setting of views off the UI thread. Now that clickable can effect the focusable state,
888     * changing the clickable attribute off the UI thread will cause an exception (since changing
889     * the focusable state checks). In order to prevent apps from crashing, we will handle this
890     * specific case and just not notify parents on new focusables resulting from marking views
891     * clickable from outside the UI thread.
892     */
893    private static boolean sAutoFocusableOffUIThreadWontNotifyParents;
894
895    /** @hide */
896    @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO})
897    @Retention(RetentionPolicy.SOURCE)
898    public @interface Focusable {}
899
900    /**
901     * This view does not want keystrokes.
902     * <p>
903     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
904     * android:focusable}.
905     */
906    public static final int NOT_FOCUSABLE = 0x00000000;
907
908    /**
909     * This view wants keystrokes.
910     * <p>
911     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
912     * android:focusable}.
913     */
914    public static final int FOCUSABLE = 0x00000001;
915
916    /**
917     * This view determines focusability automatically. This is the default.
918     * <p>
919     * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code
920     * android:focusable}.
921     */
922    public static final int FOCUSABLE_AUTO = 0x00000010;
923
924    /**
925     * Mask for use with setFlags indicating bits used for focus.
926     */
927    private static final int FOCUSABLE_MASK = 0x00000011;
928
929    /**
930     * This view will adjust its padding to fit sytem windows (e.g. status bar)
931     */
932    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
933
934    /** @hide */
935    @IntDef({VISIBLE, INVISIBLE, GONE})
936    @Retention(RetentionPolicy.SOURCE)
937    public @interface Visibility {}
938
939    /**
940     * This view is visible.
941     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
942     * android:visibility}.
943     */
944    public static final int VISIBLE = 0x00000000;
945
946    /**
947     * This view is invisible, but it still takes up space for layout purposes.
948     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
949     * android:visibility}.
950     */
951    public static final int INVISIBLE = 0x00000004;
952
953    /**
954     * This view is invisible, and it doesn't take any space for layout
955     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
956     * android:visibility}.
957     */
958    public static final int GONE = 0x00000008;
959
960    /**
961     * Mask for use with setFlags indicating bits used for visibility.
962     * {@hide}
963     */
964    static final int VISIBILITY_MASK = 0x0000000C;
965
966    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
967
968    /**
969     * Hint indicating that this view can be autofilled with an email address.
970     *
971     * <p>Can be used with either {@link #setAutofillHints(String[])} or
972     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
973     * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
974     *
975     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
976     */
977    public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
978
979    /**
980     * Hint indicating that this view can be autofilled with a user's real name.
981     *
982     * <p>Can be used with either {@link #setAutofillHints(String[])} or
983     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
984     * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
985     *
986     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
987     */
988    public static final String AUTOFILL_HINT_NAME = "name";
989
990    /**
991     * Hint indicating that this view can be autofilled with a username.
992     *
993     * <p>Can be used with either {@link #setAutofillHints(String[])} or
994     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
995     * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
996     *
997     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
998     */
999    public static final String AUTOFILL_HINT_USERNAME = "username";
1000
1001    /**
1002     * Hint indicating that this view can be autofilled with a password.
1003     *
1004     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1005     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1006     * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
1007     *
1008     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1009     */
1010    public static final String AUTOFILL_HINT_PASSWORD = "password";
1011
1012    /**
1013     * Hint indicating that this view can be autofilled with a phone number.
1014     *
1015     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1016     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1017     * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
1018     *
1019     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1020     */
1021    public static final String AUTOFILL_HINT_PHONE = "phone";
1022
1023    /**
1024     * Hint indicating that this view can be autofilled with a postal address.
1025     *
1026     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1027     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1028     * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
1029     *
1030     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1031     */
1032    public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
1033
1034    /**
1035     * Hint indicating that this view can be autofilled with a postal code.
1036     *
1037     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1038     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1039     * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
1040     *
1041     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1042     */
1043    public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
1044
1045    /**
1046     * Hint indicating that this view can be autofilled with a credit card number.
1047     *
1048     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1049     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1050     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
1051     *
1052     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1053     */
1054    public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
1055
1056    /**
1057     * Hint indicating that this view can be autofilled with a credit card security code.
1058     *
1059     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1060     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1061     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
1062     *
1063     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1064     */
1065    public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
1066
1067    /**
1068     * Hint indicating that this view can be autofilled with a credit card expiration date.
1069     *
1070     * <p>It should be used when the credit card expiration date is represented by just one view;
1071     * if it is represented by more than one (for example, one view for the month and another view
1072     * for the year), then each of these views should use the hint specific for the unit
1073     * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
1074     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
1075     * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
1076     *
1077     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1078     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1079     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
1080     *
1081     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1082     */
1083    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
1084            "creditCardExpirationDate";
1085
1086    /**
1087     * Hint indicating that this view can be autofilled with a credit card expiration month.
1088     *
1089     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1090     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1091     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
1092     *
1093     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1094     */
1095    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
1096            "creditCardExpirationMonth";
1097
1098    /**
1099     * Hint indicating that this view can be autofilled with a credit card expiration year.
1100     *
1101     * <p>Can be used with either {@link #setAutofillHints(String[])} or
1102     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
1103     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
1104     *
1105     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1106     */
1107    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
1108            "creditCardExpirationYear";
1109
1110    /**
1111     * Hint indicating that this view can be autofilled with a credit card expiration day.
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_DAY}</code>).
1116     *
1117     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
1118     */
1119    public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
1120
1121    /**
1122     * Hints for the autofill services that describes the content of the view.
1123     */
1124    private @Nullable String[] mAutofillHints;
1125
1126    /**
1127     * Autofill id, lazily created on calls to {@link #getAutofillId()}.
1128     */
1129    private AutofillId mAutofillId;
1130
1131    /** @hide */
1132    @IntDef({
1133            AUTOFILL_TYPE_NONE,
1134            AUTOFILL_TYPE_TEXT,
1135            AUTOFILL_TYPE_TOGGLE,
1136            AUTOFILL_TYPE_LIST,
1137            AUTOFILL_TYPE_DATE
1138    })
1139    @Retention(RetentionPolicy.SOURCE)
1140    public @interface AutofillType {}
1141
1142    /**
1143     * Autofill type for views that cannot be autofilled.
1144     *
1145     * <p>Typically used when the view is read-only; for example, a text label.
1146     *
1147     * @see #getAutofillType()
1148     */
1149    public static final int AUTOFILL_TYPE_NONE = 0;
1150
1151    /**
1152     * Autofill type for a text field, which is filled by a {@link CharSequence}.
1153     *
1154     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1155     * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
1156     * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
1157     *
1158     * @see #getAutofillType()
1159     */
1160    public static final int AUTOFILL_TYPE_TEXT = 1;
1161
1162    /**
1163     * Autofill type for a togglable field, which is filled by a {@code boolean}.
1164     *
1165     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1166     * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
1167     * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
1168     *
1169     * @see #getAutofillType()
1170     */
1171    public static final int AUTOFILL_TYPE_TOGGLE = 2;
1172
1173    /**
1174     * Autofill type for a selection list field, which is filled by an {@code int}
1175     * representing the element index inside the list (starting at {@code 0}).
1176     *
1177     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1178     * {@link AutofillValue#forList(int)}, and the value passed to autofill a
1179     * {@link View} can be fetched through {@link AutofillValue#getListValue()}.
1180     *
1181     * <p>The available options in the selection list are typically provided by
1182     * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
1183     *
1184     * @see #getAutofillType()
1185     */
1186    public static final int AUTOFILL_TYPE_LIST = 3;
1187
1188
1189    /**
1190     * Autofill type for a field that contains a date, which is represented by a long representing
1191     * the number of milliseconds since the standard base time known as "the epoch", namely
1192     * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}.
1193     *
1194     * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
1195     * {@link AutofillValue#forDate(long)}, and the values passed to
1196     * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
1197     *
1198     * @see #getAutofillType()
1199     */
1200    public static final int AUTOFILL_TYPE_DATE = 4;
1201
1202    /** @hide */
1203    @IntDef({
1204            IMPORTANT_FOR_AUTOFILL_AUTO,
1205            IMPORTANT_FOR_AUTOFILL_YES,
1206            IMPORTANT_FOR_AUTOFILL_NO,
1207            IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
1208            IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
1209    })
1210    @Retention(RetentionPolicy.SOURCE)
1211    public @interface AutofillImportance {}
1212
1213    /**
1214     * Automatically determine whether a view is important for autofill.
1215     *
1216     * @see #isImportantForAutofill()
1217     * @see #setImportantForAutofill(int)
1218     */
1219    public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
1220
1221    /**
1222     * The view is important for autofill, and its children (if any) will be traversed.
1223     *
1224     * @see #isImportantForAutofill()
1225     * @see #setImportantForAutofill(int)
1226     */
1227    public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
1228
1229    /**
1230     * The view is not important for autofill, but its children (if any) will be traversed.
1231     *
1232     * @see #isImportantForAutofill()
1233     * @see #setImportantForAutofill(int)
1234     */
1235    public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
1236
1237    /**
1238     * The view is important for autofill, but its children (if any) will not be traversed.
1239     *
1240     * @see #isImportantForAutofill()
1241     * @see #setImportantForAutofill(int)
1242     */
1243    public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
1244
1245    /**
1246     * The view is not important for autofill, and its children (if any) will not be traversed.
1247     *
1248     * @see #isImportantForAutofill()
1249     * @see #setImportantForAutofill(int)
1250     */
1251    public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
1252
1253    /** @hide */
1254    @IntDef(
1255            flag = true,
1256            value = {AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS})
1257    @Retention(RetentionPolicy.SOURCE)
1258    public @interface AutofillFlags {}
1259
1260    /**
1261     * Flag requesting you to add views that are marked as not important for autofill
1262     * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}.
1263     */
1264    public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
1265
1266    /**
1267     * This view is enabled. Interpretation varies by subclass.
1268     * Use with ENABLED_MASK when calling setFlags.
1269     * {@hide}
1270     */
1271    static final int ENABLED = 0x00000000;
1272
1273    /**
1274     * This view is disabled. Interpretation varies by subclass.
1275     * Use with ENABLED_MASK when calling setFlags.
1276     * {@hide}
1277     */
1278    static final int DISABLED = 0x00000020;
1279
1280   /**
1281    * Mask for use with setFlags indicating bits used for indicating whether
1282    * this view is enabled
1283    * {@hide}
1284    */
1285    static final int ENABLED_MASK = 0x00000020;
1286
1287    /**
1288     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
1289     * called and further optimizations will be performed. It is okay to have
1290     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
1291     * {@hide}
1292     */
1293    static final int WILL_NOT_DRAW = 0x00000080;
1294
1295    /**
1296     * Mask for use with setFlags indicating bits used for indicating whether
1297     * this view is will draw
1298     * {@hide}
1299     */
1300    static final int DRAW_MASK = 0x00000080;
1301
1302    /**
1303     * <p>This view doesn't show scrollbars.</p>
1304     * {@hide}
1305     */
1306    static final int SCROLLBARS_NONE = 0x00000000;
1307
1308    /**
1309     * <p>This view shows horizontal scrollbars.</p>
1310     * {@hide}
1311     */
1312    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
1313
1314    /**
1315     * <p>This view shows vertical scrollbars.</p>
1316     * {@hide}
1317     */
1318    static final int SCROLLBARS_VERTICAL = 0x00000200;
1319
1320    /**
1321     * <p>Mask for use with setFlags indicating bits used for indicating which
1322     * scrollbars are enabled.</p>
1323     * {@hide}
1324     */
1325    static final int SCROLLBARS_MASK = 0x00000300;
1326
1327    /**
1328     * Indicates that the view should filter touches when its window is obscured.
1329     * Refer to the class comments for more information about this security feature.
1330     * {@hide}
1331     */
1332    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
1333
1334    /**
1335     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
1336     * that they are optional and should be skipped if the window has
1337     * requested system UI flags that ignore those insets for layout.
1338     */
1339    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
1340
1341    /**
1342     * <p>This view doesn't show fading edges.</p>
1343     * {@hide}
1344     */
1345    static final int FADING_EDGE_NONE = 0x00000000;
1346
1347    /**
1348     * <p>This view shows horizontal fading edges.</p>
1349     * {@hide}
1350     */
1351    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
1352
1353    /**
1354     * <p>This view shows vertical fading edges.</p>
1355     * {@hide}
1356     */
1357    static final int FADING_EDGE_VERTICAL = 0x00002000;
1358
1359    /**
1360     * <p>Mask for use with setFlags indicating bits used for indicating which
1361     * fading edges are enabled.</p>
1362     * {@hide}
1363     */
1364    static final int FADING_EDGE_MASK = 0x00003000;
1365
1366    /**
1367     * <p>Indicates this view can be clicked. When clickable, a View reacts
1368     * to clicks by notifying the OnClickListener.<p>
1369     * {@hide}
1370     */
1371    static final int CLICKABLE = 0x00004000;
1372
1373    /**
1374     * <p>Indicates this view is caching its drawing into a bitmap.</p>
1375     * {@hide}
1376     */
1377    static final int DRAWING_CACHE_ENABLED = 0x00008000;
1378
1379    /**
1380     * <p>Indicates that no icicle should be saved for this view.<p>
1381     * {@hide}
1382     */
1383    static final int SAVE_DISABLED = 0x000010000;
1384
1385    /**
1386     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
1387     * property.</p>
1388     * {@hide}
1389     */
1390    static final int SAVE_DISABLED_MASK = 0x000010000;
1391
1392    /**
1393     * <p>Indicates that no drawing cache should ever be created for this view.<p>
1394     * {@hide}
1395     */
1396    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
1397
1398    /**
1399     * <p>Indicates this view can take / keep focus when int touch mode.</p>
1400     * {@hide}
1401     */
1402    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1403
1404    /** @hide */
1405    @Retention(RetentionPolicy.SOURCE)
1406    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1407    public @interface DrawingCacheQuality {}
1408
1409    /**
1410     * <p>Enables low quality mode for the drawing cache.</p>
1411     */
1412    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1413
1414    /**
1415     * <p>Enables high quality mode for the drawing cache.</p>
1416     */
1417    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1418
1419    /**
1420     * <p>Enables automatic quality mode for the drawing cache.</p>
1421     */
1422    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1423
1424    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1425            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1426    };
1427
1428    /**
1429     * <p>Mask for use with setFlags indicating bits used for the cache
1430     * quality property.</p>
1431     * {@hide}
1432     */
1433    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1434
1435    /**
1436     * <p>
1437     * Indicates this view can be long clicked. When long clickable, a View
1438     * reacts to long clicks by notifying the OnLongClickListener or showing a
1439     * context menu.
1440     * </p>
1441     * {@hide}
1442     */
1443    static final int LONG_CLICKABLE = 0x00200000;
1444
1445    /**
1446     * <p>Indicates that this view gets its drawable states from its direct parent
1447     * and ignores its original internal states.</p>
1448     *
1449     * @hide
1450     */
1451    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1452
1453    /**
1454     * <p>
1455     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1456     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1457     * OnContextClickListener.
1458     * </p>
1459     * {@hide}
1460     */
1461    static final int CONTEXT_CLICKABLE = 0x00800000;
1462
1463
1464    /** @hide */
1465    @IntDef({
1466        SCROLLBARS_INSIDE_OVERLAY,
1467        SCROLLBARS_INSIDE_INSET,
1468        SCROLLBARS_OUTSIDE_OVERLAY,
1469        SCROLLBARS_OUTSIDE_INSET
1470    })
1471    @Retention(RetentionPolicy.SOURCE)
1472    public @interface ScrollBarStyle {}
1473
1474    /**
1475     * The scrollbar style to display the scrollbars inside the content area,
1476     * without increasing the padding. The scrollbars will be overlaid with
1477     * translucency on the view's content.
1478     */
1479    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1480
1481    /**
1482     * The scrollbar style to display the scrollbars inside the padded area,
1483     * increasing the padding of the view. The scrollbars will not overlap the
1484     * content area of the view.
1485     */
1486    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1487
1488    /**
1489     * The scrollbar style to display the scrollbars at the edge of the view,
1490     * without increasing the padding. The scrollbars will be overlaid with
1491     * translucency.
1492     */
1493    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1494
1495    /**
1496     * The scrollbar style to display the scrollbars at the edge of the view,
1497     * increasing the padding of the view. The scrollbars will only overlap the
1498     * background, if any.
1499     */
1500    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1501
1502    /**
1503     * Mask to check if the scrollbar style is overlay or inset.
1504     * {@hide}
1505     */
1506    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1507
1508    /**
1509     * Mask to check if the scrollbar style is inside or outside.
1510     * {@hide}
1511     */
1512    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1513
1514    /**
1515     * Mask for scrollbar style.
1516     * {@hide}
1517     */
1518    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1519
1520    /**
1521     * View flag indicating that the screen should remain on while the
1522     * window containing this view is visible to the user.  This effectively
1523     * takes care of automatically setting the WindowManager's
1524     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1525     */
1526    public static final int KEEP_SCREEN_ON = 0x04000000;
1527
1528    /**
1529     * View flag indicating whether this view should have sound effects enabled
1530     * for events such as clicking and touching.
1531     */
1532    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1533
1534    /**
1535     * View flag indicating whether this view should have haptic feedback
1536     * enabled for events such as long presses.
1537     */
1538    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1539
1540    /**
1541     * <p>Indicates that the view hierarchy should stop saving state when
1542     * it reaches this view.  If state saving is initiated immediately at
1543     * the view, it will be allowed.
1544     * {@hide}
1545     */
1546    static final int PARENT_SAVE_DISABLED = 0x20000000;
1547
1548    /**
1549     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1550     * {@hide}
1551     */
1552    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1553
1554    private static Paint sDebugPaint;
1555
1556    /**
1557     * <p>Indicates this view can display a tooltip on hover or long press.</p>
1558     * {@hide}
1559     */
1560    static final int TOOLTIP = 0x40000000;
1561
1562    /** @hide */
1563    @IntDef(flag = true,
1564            value = {
1565                FOCUSABLES_ALL,
1566                FOCUSABLES_TOUCH_MODE
1567            })
1568    @Retention(RetentionPolicy.SOURCE)
1569    public @interface FocusableMode {}
1570
1571    /**
1572     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1573     * should add all focusable Views regardless if they are focusable in touch mode.
1574     */
1575    public static final int FOCUSABLES_ALL = 0x00000000;
1576
1577    /**
1578     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1579     * should add only Views focusable in touch mode.
1580     */
1581    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1582
1583    /** @hide */
1584    @IntDef({
1585            FOCUS_BACKWARD,
1586            FOCUS_FORWARD,
1587            FOCUS_LEFT,
1588            FOCUS_UP,
1589            FOCUS_RIGHT,
1590            FOCUS_DOWN
1591    })
1592    @Retention(RetentionPolicy.SOURCE)
1593    public @interface FocusDirection {}
1594
1595    /** @hide */
1596    @IntDef({
1597            FOCUS_LEFT,
1598            FOCUS_UP,
1599            FOCUS_RIGHT,
1600            FOCUS_DOWN
1601    })
1602    @Retention(RetentionPolicy.SOURCE)
1603    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1604
1605    /**
1606     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1607     * item.
1608     */
1609    public static final int FOCUS_BACKWARD = 0x00000001;
1610
1611    /**
1612     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1613     * item.
1614     */
1615    public static final int FOCUS_FORWARD = 0x00000002;
1616
1617    /**
1618     * Use with {@link #focusSearch(int)}. Move focus to the left.
1619     */
1620    public static final int FOCUS_LEFT = 0x00000011;
1621
1622    /**
1623     * Use with {@link #focusSearch(int)}. Move focus up.
1624     */
1625    public static final int FOCUS_UP = 0x00000021;
1626
1627    /**
1628     * Use with {@link #focusSearch(int)}. Move focus to the right.
1629     */
1630    public static final int FOCUS_RIGHT = 0x00000042;
1631
1632    /**
1633     * Use with {@link #focusSearch(int)}. Move focus down.
1634     */
1635    public static final int FOCUS_DOWN = 0x00000082;
1636
1637    /**
1638     * Bits of {@link #getMeasuredWidthAndState()} and
1639     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1640     */
1641    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1642
1643    /**
1644     * Bits of {@link #getMeasuredWidthAndState()} and
1645     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1646     */
1647    public static final int MEASURED_STATE_MASK = 0xff000000;
1648
1649    /**
1650     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1651     * for functions that combine both width and height into a single int,
1652     * such as {@link #getMeasuredState()} and the childState argument of
1653     * {@link #resolveSizeAndState(int, int, int)}.
1654     */
1655    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1656
1657    /**
1658     * Bit of {@link #getMeasuredWidthAndState()} and
1659     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1660     * is smaller that the space the view would like to have.
1661     */
1662    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1663
1664    /**
1665     * Base View state sets
1666     */
1667    // Singles
1668    /**
1669     * Indicates the view has no states set. States are used with
1670     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1671     * view depending on its state.
1672     *
1673     * @see android.graphics.drawable.Drawable
1674     * @see #getDrawableState()
1675     */
1676    protected static final int[] EMPTY_STATE_SET;
1677    /**
1678     * Indicates the view is enabled. States are used with
1679     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1680     * view depending on its state.
1681     *
1682     * @see android.graphics.drawable.Drawable
1683     * @see #getDrawableState()
1684     */
1685    protected static final int[] ENABLED_STATE_SET;
1686    /**
1687     * Indicates the view is focused. States are used with
1688     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1689     * view depending on its state.
1690     *
1691     * @see android.graphics.drawable.Drawable
1692     * @see #getDrawableState()
1693     */
1694    protected static final int[] FOCUSED_STATE_SET;
1695    /**
1696     * Indicates the view is selected. States are used with
1697     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1698     * view depending on its state.
1699     *
1700     * @see android.graphics.drawable.Drawable
1701     * @see #getDrawableState()
1702     */
1703    protected static final int[] SELECTED_STATE_SET;
1704    /**
1705     * Indicates the view is pressed. States are used with
1706     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1707     * view depending on its state.
1708     *
1709     * @see android.graphics.drawable.Drawable
1710     * @see #getDrawableState()
1711     */
1712    protected static final int[] PRESSED_STATE_SET;
1713    /**
1714     * Indicates the view's window has focus. States are used with
1715     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1716     * view depending on its state.
1717     *
1718     * @see android.graphics.drawable.Drawable
1719     * @see #getDrawableState()
1720     */
1721    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1722    // Doubles
1723    /**
1724     * Indicates the view is enabled and has the focus.
1725     *
1726     * @see #ENABLED_STATE_SET
1727     * @see #FOCUSED_STATE_SET
1728     */
1729    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1730    /**
1731     * Indicates the view is enabled and selected.
1732     *
1733     * @see #ENABLED_STATE_SET
1734     * @see #SELECTED_STATE_SET
1735     */
1736    protected static final int[] ENABLED_SELECTED_STATE_SET;
1737    /**
1738     * Indicates the view is enabled and that its window has focus.
1739     *
1740     * @see #ENABLED_STATE_SET
1741     * @see #WINDOW_FOCUSED_STATE_SET
1742     */
1743    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1744    /**
1745     * Indicates the view is focused and selected.
1746     *
1747     * @see #FOCUSED_STATE_SET
1748     * @see #SELECTED_STATE_SET
1749     */
1750    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1751    /**
1752     * Indicates the view has the focus and that its window has the focus.
1753     *
1754     * @see #FOCUSED_STATE_SET
1755     * @see #WINDOW_FOCUSED_STATE_SET
1756     */
1757    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1758    /**
1759     * Indicates the view is selected and that its window has the focus.
1760     *
1761     * @see #SELECTED_STATE_SET
1762     * @see #WINDOW_FOCUSED_STATE_SET
1763     */
1764    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1765    // Triples
1766    /**
1767     * Indicates the view is enabled, focused and selected.
1768     *
1769     * @see #ENABLED_STATE_SET
1770     * @see #FOCUSED_STATE_SET
1771     * @see #SELECTED_STATE_SET
1772     */
1773    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1774    /**
1775     * Indicates the view is enabled, focused and its window has the focus.
1776     *
1777     * @see #ENABLED_STATE_SET
1778     * @see #FOCUSED_STATE_SET
1779     * @see #WINDOW_FOCUSED_STATE_SET
1780     */
1781    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1782    /**
1783     * Indicates the view is enabled, selected and its window has the focus.
1784     *
1785     * @see #ENABLED_STATE_SET
1786     * @see #SELECTED_STATE_SET
1787     * @see #WINDOW_FOCUSED_STATE_SET
1788     */
1789    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1790    /**
1791     * Indicates the view is focused, selected and its window has the focus.
1792     *
1793     * @see #FOCUSED_STATE_SET
1794     * @see #SELECTED_STATE_SET
1795     * @see #WINDOW_FOCUSED_STATE_SET
1796     */
1797    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1798    /**
1799     * Indicates the view is enabled, focused, selected and its window
1800     * has the focus.
1801     *
1802     * @see #ENABLED_STATE_SET
1803     * @see #FOCUSED_STATE_SET
1804     * @see #SELECTED_STATE_SET
1805     * @see #WINDOW_FOCUSED_STATE_SET
1806     */
1807    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1808    /**
1809     * Indicates the view is pressed and its window has the focus.
1810     *
1811     * @see #PRESSED_STATE_SET
1812     * @see #WINDOW_FOCUSED_STATE_SET
1813     */
1814    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1815    /**
1816     * Indicates the view is pressed and selected.
1817     *
1818     * @see #PRESSED_STATE_SET
1819     * @see #SELECTED_STATE_SET
1820     */
1821    protected static final int[] PRESSED_SELECTED_STATE_SET;
1822    /**
1823     * Indicates the view is pressed, selected and its window has the focus.
1824     *
1825     * @see #PRESSED_STATE_SET
1826     * @see #SELECTED_STATE_SET
1827     * @see #WINDOW_FOCUSED_STATE_SET
1828     */
1829    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1830    /**
1831     * Indicates the view is pressed and focused.
1832     *
1833     * @see #PRESSED_STATE_SET
1834     * @see #FOCUSED_STATE_SET
1835     */
1836    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1837    /**
1838     * Indicates the view is pressed, focused and its window has the focus.
1839     *
1840     * @see #PRESSED_STATE_SET
1841     * @see #FOCUSED_STATE_SET
1842     * @see #WINDOW_FOCUSED_STATE_SET
1843     */
1844    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1845    /**
1846     * Indicates the view is pressed, focused and selected.
1847     *
1848     * @see #PRESSED_STATE_SET
1849     * @see #SELECTED_STATE_SET
1850     * @see #FOCUSED_STATE_SET
1851     */
1852    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1853    /**
1854     * Indicates the view is pressed, focused, selected and its window has the focus.
1855     *
1856     * @see #PRESSED_STATE_SET
1857     * @see #FOCUSED_STATE_SET
1858     * @see #SELECTED_STATE_SET
1859     * @see #WINDOW_FOCUSED_STATE_SET
1860     */
1861    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1862    /**
1863     * Indicates the view is pressed and enabled.
1864     *
1865     * @see #PRESSED_STATE_SET
1866     * @see #ENABLED_STATE_SET
1867     */
1868    protected static final int[] PRESSED_ENABLED_STATE_SET;
1869    /**
1870     * Indicates the view is pressed, enabled and its window has the focus.
1871     *
1872     * @see #PRESSED_STATE_SET
1873     * @see #ENABLED_STATE_SET
1874     * @see #WINDOW_FOCUSED_STATE_SET
1875     */
1876    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1877    /**
1878     * Indicates the view is pressed, enabled and selected.
1879     *
1880     * @see #PRESSED_STATE_SET
1881     * @see #ENABLED_STATE_SET
1882     * @see #SELECTED_STATE_SET
1883     */
1884    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1885    /**
1886     * Indicates the view is pressed, enabled, selected and its window has the
1887     * focus.
1888     *
1889     * @see #PRESSED_STATE_SET
1890     * @see #ENABLED_STATE_SET
1891     * @see #SELECTED_STATE_SET
1892     * @see #WINDOW_FOCUSED_STATE_SET
1893     */
1894    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1895    /**
1896     * Indicates the view is pressed, enabled and focused.
1897     *
1898     * @see #PRESSED_STATE_SET
1899     * @see #ENABLED_STATE_SET
1900     * @see #FOCUSED_STATE_SET
1901     */
1902    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1903    /**
1904     * Indicates the view is pressed, enabled, focused and its window has the
1905     * focus.
1906     *
1907     * @see #PRESSED_STATE_SET
1908     * @see #ENABLED_STATE_SET
1909     * @see #FOCUSED_STATE_SET
1910     * @see #WINDOW_FOCUSED_STATE_SET
1911     */
1912    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1913    /**
1914     * Indicates the view is pressed, enabled, focused and selected.
1915     *
1916     * @see #PRESSED_STATE_SET
1917     * @see #ENABLED_STATE_SET
1918     * @see #SELECTED_STATE_SET
1919     * @see #FOCUSED_STATE_SET
1920     */
1921    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1922    /**
1923     * Indicates the view is pressed, enabled, focused, selected and its window
1924     * has the focus.
1925     *
1926     * @see #PRESSED_STATE_SET
1927     * @see #ENABLED_STATE_SET
1928     * @see #SELECTED_STATE_SET
1929     * @see #FOCUSED_STATE_SET
1930     * @see #WINDOW_FOCUSED_STATE_SET
1931     */
1932    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1933
1934    static {
1935        EMPTY_STATE_SET = StateSet.get(0);
1936
1937        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1938
1939        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1940        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1941                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1942
1943        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1944        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1945                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1946        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1947                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1948        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1949                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1950                        | StateSet.VIEW_STATE_FOCUSED);
1951
1952        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1953        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1954                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1955        ENABLED_SELECTED_STATE_SET = StateSet.get(
1956                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1957        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1958                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1959                        | StateSet.VIEW_STATE_ENABLED);
1960        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1961                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1962        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1963                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1964                        | StateSet.VIEW_STATE_ENABLED);
1965        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1966                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1967                        | StateSet.VIEW_STATE_ENABLED);
1968        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1969                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1970                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1971
1972        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1973        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1974                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1975        PRESSED_SELECTED_STATE_SET = StateSet.get(
1976                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1977        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1978                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1979                        | StateSet.VIEW_STATE_PRESSED);
1980        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1981                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1982        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1983                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1984                        | StateSet.VIEW_STATE_PRESSED);
1985        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1986                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1987                        | StateSet.VIEW_STATE_PRESSED);
1988        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1989                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1990                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1991        PRESSED_ENABLED_STATE_SET = StateSet.get(
1992                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1993        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1994                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1995                        | StateSet.VIEW_STATE_PRESSED);
1996        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1997                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1998                        | StateSet.VIEW_STATE_PRESSED);
1999        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2000                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2001                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2002        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
2003                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
2004                        | StateSet.VIEW_STATE_PRESSED);
2005        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2006                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
2007                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2008        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
2009                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
2010                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
2011        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
2012                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
2013                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
2014                        | StateSet.VIEW_STATE_PRESSED);
2015    }
2016
2017    /**
2018     * Accessibility event types that are dispatched for text population.
2019     */
2020    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
2021            AccessibilityEvent.TYPE_VIEW_CLICKED
2022            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
2023            | AccessibilityEvent.TYPE_VIEW_SELECTED
2024            | AccessibilityEvent.TYPE_VIEW_FOCUSED
2025            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
2026            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
2027            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
2028            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
2029            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
2030            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
2031            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
2032
2033    static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255);
2034
2035    static final int DEBUG_CORNERS_SIZE_DIP = 8;
2036
2037    /**
2038     * Temporary Rect currently for use in setBackground().  This will probably
2039     * be extended in the future to hold our own class with more than just
2040     * a Rect. :)
2041     */
2042    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
2043
2044    /**
2045     * Map used to store views' tags.
2046     */
2047    private SparseArray<Object> mKeyedTags;
2048
2049    /**
2050     * The next available accessibility id.
2051     */
2052    private static int sNextAccessibilityViewId;
2053
2054    /**
2055     * The animation currently associated with this view.
2056     * @hide
2057     */
2058    protected Animation mCurrentAnimation = null;
2059
2060    /**
2061     * Width as measured during measure pass.
2062     * {@hide}
2063     */
2064    @ViewDebug.ExportedProperty(category = "measurement")
2065    int mMeasuredWidth;
2066
2067    /**
2068     * Height as measured during measure pass.
2069     * {@hide}
2070     */
2071    @ViewDebug.ExportedProperty(category = "measurement")
2072    int mMeasuredHeight;
2073
2074    /**
2075     * Flag to indicate that this view was marked INVALIDATED, or had its display list
2076     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
2077     * its display list. This flag, used only when hw accelerated, allows us to clear the
2078     * flag while retaining this information until it's needed (at getDisplayList() time and
2079     * in drawChild(), when we decide to draw a view's children's display lists into our own).
2080     *
2081     * {@hide}
2082     */
2083    boolean mRecreateDisplayList = false;
2084
2085    /**
2086     * The view's identifier.
2087     * {@hide}
2088     *
2089     * @see #setId(int)
2090     * @see #getId()
2091     */
2092    @IdRes
2093    @ViewDebug.ExportedProperty(resolveId = true)
2094    int mID = NO_ID;
2095
2096    /** The ID of this view for autofill purposes.
2097     * <ul>
2098     *     <li>== {@link #NO_ID}: ID has not been assigned yet
2099     *     <li>&le; {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is
2100     *                                                  unique in the process. This might change
2101     *                                                  over activity lifecycle events.
2102     *     <li>&gt; {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is
2103     *                                                  unique in the activity. This stays the same
2104     *                                                  over activity lifecycle events.
2105     */
2106    private int mAutofillViewId = NO_ID;
2107
2108    // ID for accessibility purposes. This ID must be unique for every window
2109    private int mAccessibilityViewId = NO_ID;
2110
2111    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
2112
2113    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
2114
2115    /**
2116     * The view's tag.
2117     * {@hide}
2118     *
2119     * @see #setTag(Object)
2120     * @see #getTag()
2121     */
2122    protected Object mTag = null;
2123
2124    // for mPrivateFlags:
2125    /** {@hide} */
2126    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
2127    /** {@hide} */
2128    static final int PFLAG_FOCUSED                     = 0x00000002;
2129    /** {@hide} */
2130    static final int PFLAG_SELECTED                    = 0x00000004;
2131    /** {@hide} */
2132    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
2133    /** {@hide} */
2134    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
2135    /** {@hide} */
2136    static final int PFLAG_DRAWN                       = 0x00000020;
2137    /**
2138     * When this flag is set, this view is running an animation on behalf of its
2139     * children and should therefore not cancel invalidate requests, even if they
2140     * lie outside of this view's bounds.
2141     *
2142     * {@hide}
2143     */
2144    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
2145    /** {@hide} */
2146    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
2147    /** {@hide} */
2148    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
2149    /** {@hide} */
2150    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
2151    /** {@hide} */
2152    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
2153    /** {@hide} */
2154    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
2155    /** {@hide} */
2156    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
2157
2158    private static final int PFLAG_PRESSED             = 0x00004000;
2159
2160    /** {@hide} */
2161    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
2162    /**
2163     * Flag used to indicate that this view should be drawn once more (and only once
2164     * more) after its animation has completed.
2165     * {@hide}
2166     */
2167    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
2168
2169    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
2170
2171    /**
2172     * Indicates that the View returned true when onSetAlpha() was called and that
2173     * the alpha must be restored.
2174     * {@hide}
2175     */
2176    static final int PFLAG_ALPHA_SET                   = 0x00040000;
2177
2178    /**
2179     * Set by {@link #setScrollContainer(boolean)}.
2180     */
2181    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
2182
2183    /**
2184     * Set by {@link #setScrollContainer(boolean)}.
2185     */
2186    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
2187
2188    /**
2189     * View flag indicating whether this view was invalidated (fully or partially.)
2190     *
2191     * @hide
2192     */
2193    static final int PFLAG_DIRTY                       = 0x00200000;
2194
2195    /**
2196     * View flag indicating whether this view was invalidated by an opaque
2197     * invalidate request.
2198     *
2199     * @hide
2200     */
2201    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
2202
2203    /**
2204     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
2205     *
2206     * @hide
2207     */
2208    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
2209
2210    /**
2211     * Indicates whether the background is opaque.
2212     *
2213     * @hide
2214     */
2215    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
2216
2217    /**
2218     * Indicates whether the scrollbars are opaque.
2219     *
2220     * @hide
2221     */
2222    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
2223
2224    /**
2225     * Indicates whether the view is opaque.
2226     *
2227     * @hide
2228     */
2229    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
2230
2231    /**
2232     * Indicates a prepressed state;
2233     * the short time between ACTION_DOWN and recognizing
2234     * a 'real' press. Prepressed is used to recognize quick taps
2235     * even when they are shorter than ViewConfiguration.getTapTimeout().
2236     *
2237     * @hide
2238     */
2239    private static final int PFLAG_PREPRESSED          = 0x02000000;
2240
2241    /**
2242     * Indicates whether the view is temporarily detached.
2243     *
2244     * @hide
2245     */
2246    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
2247
2248    /**
2249     * Indicates that we should awaken scroll bars once attached
2250     *
2251     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
2252     * during window attachment and it is no longer needed. Feel free to repurpose it.
2253     *
2254     * @hide
2255     */
2256    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
2257
2258    /**
2259     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
2260     * @hide
2261     */
2262    private static final int PFLAG_HOVERED             = 0x10000000;
2263
2264    /**
2265     * no longer needed, should be reused
2266     */
2267    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
2268
2269    /** {@hide} */
2270    static final int PFLAG_ACTIVATED                   = 0x40000000;
2271
2272    /**
2273     * Indicates that this view was specifically invalidated, not just dirtied because some
2274     * child view was invalidated. The flag is used to determine when we need to recreate
2275     * a view's display list (as opposed to just returning a reference to its existing
2276     * display list).
2277     *
2278     * @hide
2279     */
2280    static final int PFLAG_INVALIDATED                 = 0x80000000;
2281
2282    /**
2283     * Masks for mPrivateFlags2, as generated by dumpFlags():
2284     *
2285     * |-------|-------|-------|-------|
2286     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
2287     *                                1  PFLAG2_DRAG_HOVERED
2288     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
2289     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
2290     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
2291     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
2292     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
2293     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
2294     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
2295     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
2296     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
2297     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
2298     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
2299     *                         111       PFLAG2_TEXT_DIRECTION_MASK
2300     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
2301     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
2302     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
2303     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
2304     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
2305     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
2306     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
2307     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
2308     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
2309     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
2310     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
2311     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
2312     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
2313     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
2314     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
2315     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
2316     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
2317     *     1                             PFLAG2_VIEW_QUICK_REJECTED
2318     *    1                              PFLAG2_PADDING_RESOLVED
2319     *   1                               PFLAG2_DRAWABLE_RESOLVED
2320     *  1                                PFLAG2_HAS_TRANSIENT_STATE
2321     * |-------|-------|-------|-------|
2322     */
2323
2324    /**
2325     * Indicates that this view has reported that it can accept the current drag's content.
2326     * Cleared when the drag operation concludes.
2327     * @hide
2328     */
2329    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
2330
2331    /**
2332     * Indicates that this view is currently directly under the drag location in a
2333     * drag-and-drop operation involving content that it can accept.  Cleared when
2334     * the drag exits the view, or when the drag operation concludes.
2335     * @hide
2336     */
2337    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
2338
2339    /** @hide */
2340    @IntDef({
2341        LAYOUT_DIRECTION_LTR,
2342        LAYOUT_DIRECTION_RTL,
2343        LAYOUT_DIRECTION_INHERIT,
2344        LAYOUT_DIRECTION_LOCALE
2345    })
2346    @Retention(RetentionPolicy.SOURCE)
2347    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
2348    public @interface LayoutDir {}
2349
2350    /** @hide */
2351    @IntDef({
2352        LAYOUT_DIRECTION_LTR,
2353        LAYOUT_DIRECTION_RTL
2354    })
2355    @Retention(RetentionPolicy.SOURCE)
2356    public @interface ResolvedLayoutDir {}
2357
2358    /**
2359     * A flag to indicate that the layout direction of this view has not been defined yet.
2360     * @hide
2361     */
2362    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
2363
2364    /**
2365     * Horizontal layout direction of this view is from Left to Right.
2366     * Use with {@link #setLayoutDirection}.
2367     */
2368    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
2369
2370    /**
2371     * Horizontal layout direction of this view is from Right to Left.
2372     * Use with {@link #setLayoutDirection}.
2373     */
2374    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
2375
2376    /**
2377     * Horizontal layout direction of this view is inherited from its parent.
2378     * Use with {@link #setLayoutDirection}.
2379     */
2380    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
2381
2382    /**
2383     * Horizontal layout direction of this view is from deduced from the default language
2384     * script for the locale. Use with {@link #setLayoutDirection}.
2385     */
2386    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
2387
2388    /**
2389     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2390     * @hide
2391     */
2392    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
2393
2394    /**
2395     * Mask for use with private flags indicating bits used for horizontal layout direction.
2396     * @hide
2397     */
2398    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2399
2400    /**
2401     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
2402     * right-to-left direction.
2403     * @hide
2404     */
2405    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2406
2407    /**
2408     * Indicates whether the view horizontal layout direction has been resolved.
2409     * @hide
2410     */
2411    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2412
2413    /**
2414     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
2415     * @hide
2416     */
2417    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
2418            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
2419
2420    /*
2421     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
2422     * flag value.
2423     * @hide
2424     */
2425    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2426            LAYOUT_DIRECTION_LTR,
2427            LAYOUT_DIRECTION_RTL,
2428            LAYOUT_DIRECTION_INHERIT,
2429            LAYOUT_DIRECTION_LOCALE
2430    };
2431
2432    /**
2433     * Default horizontal layout direction.
2434     */
2435    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2436
2437    /**
2438     * Default horizontal layout direction.
2439     * @hide
2440     */
2441    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2442
2443    /**
2444     * Text direction is inherited through {@link ViewGroup}
2445     */
2446    public static final int TEXT_DIRECTION_INHERIT = 0;
2447
2448    /**
2449     * Text direction is using "first strong algorithm". The first strong directional character
2450     * determines the paragraph direction. If there is no strong directional character, the
2451     * paragraph direction is the view's resolved layout direction.
2452     */
2453    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2454
2455    /**
2456     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2457     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2458     * If there are neither, the paragraph direction is the view's resolved layout direction.
2459     */
2460    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2461
2462    /**
2463     * Text direction is forced to LTR.
2464     */
2465    public static final int TEXT_DIRECTION_LTR = 3;
2466
2467    /**
2468     * Text direction is forced to RTL.
2469     */
2470    public static final int TEXT_DIRECTION_RTL = 4;
2471
2472    /**
2473     * Text direction is coming from the system Locale.
2474     */
2475    public static final int TEXT_DIRECTION_LOCALE = 5;
2476
2477    /**
2478     * Text direction is using "first strong algorithm". The first strong directional character
2479     * determines the paragraph direction. If there is no strong directional character, the
2480     * paragraph direction is LTR.
2481     */
2482    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2483
2484    /**
2485     * Text direction is using "first strong algorithm". The first strong directional character
2486     * determines the paragraph direction. If there is no strong directional character, the
2487     * paragraph direction is RTL.
2488     */
2489    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2490
2491    /**
2492     * Default text direction is inherited
2493     */
2494    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2495
2496    /**
2497     * Default resolved text direction
2498     * @hide
2499     */
2500    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2501
2502    /**
2503     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2504     * @hide
2505     */
2506    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2507
2508    /**
2509     * Mask for use with private flags indicating bits used for text direction.
2510     * @hide
2511     */
2512    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2513            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2514
2515    /**
2516     * Array of text direction flags for mapping attribute "textDirection" to correct
2517     * flag value.
2518     * @hide
2519     */
2520    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2521            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2522            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2523            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2524            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2525            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2526            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2527            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2528            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2529    };
2530
2531    /**
2532     * Indicates whether the view text direction has been resolved.
2533     * @hide
2534     */
2535    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2536            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2537
2538    /**
2539     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2540     * @hide
2541     */
2542    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2543
2544    /**
2545     * Mask for use with private flags indicating bits used for resolved text direction.
2546     * @hide
2547     */
2548    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2549            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2550
2551    /**
2552     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2553     * @hide
2554     */
2555    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2556            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2557
2558    /** @hide */
2559    @IntDef({
2560        TEXT_ALIGNMENT_INHERIT,
2561        TEXT_ALIGNMENT_GRAVITY,
2562        TEXT_ALIGNMENT_CENTER,
2563        TEXT_ALIGNMENT_TEXT_START,
2564        TEXT_ALIGNMENT_TEXT_END,
2565        TEXT_ALIGNMENT_VIEW_START,
2566        TEXT_ALIGNMENT_VIEW_END
2567    })
2568    @Retention(RetentionPolicy.SOURCE)
2569    public @interface TextAlignment {}
2570
2571    /**
2572     * Default text alignment. The text alignment of this View is inherited from its parent.
2573     * Use with {@link #setTextAlignment(int)}
2574     */
2575    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2576
2577    /**
2578     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2579     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2580     *
2581     * Use with {@link #setTextAlignment(int)}
2582     */
2583    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2584
2585    /**
2586     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2587     *
2588     * Use with {@link #setTextAlignment(int)}
2589     */
2590    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2591
2592    /**
2593     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2594     *
2595     * Use with {@link #setTextAlignment(int)}
2596     */
2597    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2598
2599    /**
2600     * Center the paragraph, e.g. ALIGN_CENTER.
2601     *
2602     * Use with {@link #setTextAlignment(int)}
2603     */
2604    public static final int TEXT_ALIGNMENT_CENTER = 4;
2605
2606    /**
2607     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2608     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2609     *
2610     * Use with {@link #setTextAlignment(int)}
2611     */
2612    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2613
2614    /**
2615     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2616     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2617     *
2618     * Use with {@link #setTextAlignment(int)}
2619     */
2620    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2621
2622    /**
2623     * Default text alignment is inherited
2624     */
2625    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2626
2627    /**
2628     * Default resolved text alignment
2629     * @hide
2630     */
2631    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2632
2633    /**
2634      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2635      * @hide
2636      */
2637    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2638
2639    /**
2640      * Mask for use with private flags indicating bits used for text alignment.
2641      * @hide
2642      */
2643    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2644
2645    /**
2646     * Array of text direction flags for mapping attribute "textAlignment" to correct
2647     * flag value.
2648     * @hide
2649     */
2650    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2651            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2652            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2653            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2654            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2655            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2656            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2657            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2658    };
2659
2660    /**
2661     * Indicates whether the view text alignment has been resolved.
2662     * @hide
2663     */
2664    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2665
2666    /**
2667     * Bit shift to get the resolved text alignment.
2668     * @hide
2669     */
2670    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2671
2672    /**
2673     * Mask for use with private flags indicating bits used for text alignment.
2674     * @hide
2675     */
2676    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2677            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2678
2679    /**
2680     * Indicates whether if the view text alignment has been resolved to gravity
2681     */
2682    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2683            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2684
2685    // Accessiblity constants for mPrivateFlags2
2686
2687    /**
2688     * Shift for the bits in {@link #mPrivateFlags2} related to the
2689     * "importantForAccessibility" attribute.
2690     */
2691    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2692
2693    /**
2694     * Automatically determine whether a view is important for accessibility.
2695     */
2696    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2697
2698    /**
2699     * The view is important for accessibility.
2700     */
2701    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2702
2703    /**
2704     * The view is not important for accessibility.
2705     */
2706    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2707
2708    /**
2709     * The view is not important for accessibility, nor are any of its
2710     * descendant views.
2711     */
2712    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2713
2714    /**
2715     * The default whether the view is important for accessibility.
2716     */
2717    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2718
2719    /**
2720     * Mask for obtaining the bits which specify how to determine
2721     * whether a view is important for accessibility.
2722     */
2723    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2724        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2725        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2726        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2727
2728    /**
2729     * Shift for the bits in {@link #mPrivateFlags2} related to the
2730     * "accessibilityLiveRegion" attribute.
2731     */
2732    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2733
2734    /**
2735     * Live region mode specifying that accessibility services should not
2736     * automatically announce changes to this view. This is the default live
2737     * region mode for most views.
2738     * <p>
2739     * Use with {@link #setAccessibilityLiveRegion(int)}.
2740     */
2741    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2742
2743    /**
2744     * Live region mode specifying that accessibility services should announce
2745     * changes to this view.
2746     * <p>
2747     * Use with {@link #setAccessibilityLiveRegion(int)}.
2748     */
2749    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2750
2751    /**
2752     * Live region mode specifying that accessibility services should interrupt
2753     * ongoing speech to immediately announce changes to this view.
2754     * <p>
2755     * Use with {@link #setAccessibilityLiveRegion(int)}.
2756     */
2757    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2758
2759    /**
2760     * The default whether the view is important for accessibility.
2761     */
2762    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2763
2764    /**
2765     * Mask for obtaining the bits which specify a view's accessibility live
2766     * region mode.
2767     */
2768    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2769            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2770            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2771
2772    /**
2773     * Flag indicating whether a view has accessibility focus.
2774     */
2775    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2776
2777    /**
2778     * Flag whether the accessibility state of the subtree rooted at this view changed.
2779     */
2780    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2781
2782    /**
2783     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2784     * is used to check whether later changes to the view's transform should invalidate the
2785     * view to force the quickReject test to run again.
2786     */
2787    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2788
2789    /**
2790     * Flag indicating that start/end padding has been resolved into left/right padding
2791     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2792     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2793     * during measurement. In some special cases this is required such as when an adapter-based
2794     * view measures prospective children without attaching them to a window.
2795     */
2796    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2797
2798    /**
2799     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2800     */
2801    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2802
2803    /**
2804     * Indicates that the view is tracking some sort of transient state
2805     * that the app should not need to be aware of, but that the framework
2806     * should take special care to preserve.
2807     */
2808    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2809
2810    /**
2811     * Group of bits indicating that RTL properties resolution is done.
2812     */
2813    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2814            PFLAG2_TEXT_DIRECTION_RESOLVED |
2815            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2816            PFLAG2_PADDING_RESOLVED |
2817            PFLAG2_DRAWABLE_RESOLVED;
2818
2819    // There are a couple of flags left in mPrivateFlags2
2820
2821    /* End of masks for mPrivateFlags2 */
2822
2823    /**
2824     * Masks for mPrivateFlags3, as generated by dumpFlags():
2825     *
2826     * |-------|-------|-------|-------|
2827     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2828     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2829     *                               1   PFLAG3_IS_LAID_OUT
2830     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2831     *                             1     PFLAG3_CALLED_SUPER
2832     *                            1      PFLAG3_APPLYING_INSETS
2833     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2834     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2835     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2836     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2837     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2838     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2839     *                     1             PFLAG3_SCROLL_INDICATOR_START
2840     *                    1              PFLAG3_SCROLL_INDICATOR_END
2841     *                   1               PFLAG3_ASSIST_BLOCKED
2842     *                  1                PFLAG3_CLUSTER
2843     *                 1                 PFLAG3_IS_AUTOFILLED
2844     *                1                  PFLAG3_FINGER_DOWN
2845     *               1                   PFLAG3_FOCUSED_BY_DEFAULT
2846     *           1111                    PFLAG3_IMPORTANT_FOR_AUTOFILL
2847     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
2848     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
2849     *        1                          PFLAG3_TEMPORARY_DETACH
2850     *       1                           PFLAG3_NO_REVEAL_ON_FOCUS
2851     *      1                            PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT
2852     * |-------|-------|-------|-------|
2853     */
2854
2855    /**
2856     * Flag indicating that view has a transform animation set on it. This is used to track whether
2857     * an animation is cleared between successive frames, in order to tell the associated
2858     * DisplayList to clear its animation matrix.
2859     */
2860    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2861
2862    /**
2863     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2864     * animation is cleared between successive frames, in order to tell the associated
2865     * DisplayList to restore its alpha value.
2866     */
2867    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2868
2869    /**
2870     * Flag indicating that the view has been through at least one layout since it
2871     * was last attached to a window.
2872     */
2873    static final int PFLAG3_IS_LAID_OUT = 0x4;
2874
2875    /**
2876     * Flag indicating that a call to measure() was skipped and should be done
2877     * instead when layout() is invoked.
2878     */
2879    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2880
2881    /**
2882     * Flag indicating that an overridden method correctly called down to
2883     * the superclass implementation as required by the API spec.
2884     */
2885    static final int PFLAG3_CALLED_SUPER = 0x10;
2886
2887    /**
2888     * Flag indicating that we're in the process of applying window insets.
2889     */
2890    static final int PFLAG3_APPLYING_INSETS = 0x20;
2891
2892    /**
2893     * Flag indicating that we're in the process of fitting system windows using the old method.
2894     */
2895    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2896
2897    /**
2898     * Flag indicating that nested scrolling is enabled for this view.
2899     * The view will optionally cooperate with views up its parent chain to allow for
2900     * integrated nested scrolling along the same axis.
2901     */
2902    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2903
2904    /**
2905     * Flag indicating that the bottom scroll indicator should be displayed
2906     * when this view can scroll up.
2907     */
2908    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2909
2910    /**
2911     * Flag indicating that the bottom scroll indicator should be displayed
2912     * when this view can scroll down.
2913     */
2914    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2915
2916    /**
2917     * Flag indicating that the left scroll indicator should be displayed
2918     * when this view can scroll left.
2919     */
2920    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2921
2922    /**
2923     * Flag indicating that the right scroll indicator should be displayed
2924     * when this view can scroll right.
2925     */
2926    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2927
2928    /**
2929     * Flag indicating that the start scroll indicator should be displayed
2930     * when this view can scroll in the start direction.
2931     */
2932    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2933
2934    /**
2935     * Flag indicating that the end scroll indicator should be displayed
2936     * when this view can scroll in the end direction.
2937     */
2938    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2939
2940    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2941
2942    static final int SCROLL_INDICATORS_NONE = 0x0000;
2943
2944    /**
2945     * Mask for use with setFlags indicating bits used for indicating which
2946     * scroll indicators are enabled.
2947     */
2948    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2949            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2950            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2951            | PFLAG3_SCROLL_INDICATOR_END;
2952
2953    /**
2954     * Left-shift required to translate between public scroll indicator flags
2955     * and internal PFLAGS3 flags. When used as a right-shift, translates
2956     * PFLAGS3 flags to public flags.
2957     */
2958    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2959
2960    /** @hide */
2961    @Retention(RetentionPolicy.SOURCE)
2962    @IntDef(flag = true,
2963            value = {
2964                    SCROLL_INDICATOR_TOP,
2965                    SCROLL_INDICATOR_BOTTOM,
2966                    SCROLL_INDICATOR_LEFT,
2967                    SCROLL_INDICATOR_RIGHT,
2968                    SCROLL_INDICATOR_START,
2969                    SCROLL_INDICATOR_END,
2970            })
2971    public @interface ScrollIndicators {}
2972
2973    /**
2974     * Scroll indicator direction for the top edge of the view.
2975     *
2976     * @see #setScrollIndicators(int)
2977     * @see #setScrollIndicators(int, int)
2978     * @see #getScrollIndicators()
2979     */
2980    public static final int SCROLL_INDICATOR_TOP =
2981            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2982
2983    /**
2984     * Scroll indicator direction for the bottom edge of the view.
2985     *
2986     * @see #setScrollIndicators(int)
2987     * @see #setScrollIndicators(int, int)
2988     * @see #getScrollIndicators()
2989     */
2990    public static final int SCROLL_INDICATOR_BOTTOM =
2991            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2992
2993    /**
2994     * Scroll indicator direction for the left edge of the view.
2995     *
2996     * @see #setScrollIndicators(int)
2997     * @see #setScrollIndicators(int, int)
2998     * @see #getScrollIndicators()
2999     */
3000    public static final int SCROLL_INDICATOR_LEFT =
3001            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3002
3003    /**
3004     * Scroll indicator direction for the right edge of the view.
3005     *
3006     * @see #setScrollIndicators(int)
3007     * @see #setScrollIndicators(int, int)
3008     * @see #getScrollIndicators()
3009     */
3010    public static final int SCROLL_INDICATOR_RIGHT =
3011            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3012
3013    /**
3014     * Scroll indicator direction for the starting edge of the view.
3015     * <p>
3016     * Resolved according to the view's layout direction, see
3017     * {@link #getLayoutDirection()} for more information.
3018     *
3019     * @see #setScrollIndicators(int)
3020     * @see #setScrollIndicators(int, int)
3021     * @see #getScrollIndicators()
3022     */
3023    public static final int SCROLL_INDICATOR_START =
3024            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3025
3026    /**
3027     * Scroll indicator direction for the ending edge of the view.
3028     * <p>
3029     * Resolved according to the view's layout direction, see
3030     * {@link #getLayoutDirection()} for more information.
3031     *
3032     * @see #setScrollIndicators(int)
3033     * @see #setScrollIndicators(int, int)
3034     * @see #getScrollIndicators()
3035     */
3036    public static final int SCROLL_INDICATOR_END =
3037            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
3038
3039    /**
3040     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
3041     * into this view.<p>
3042     */
3043    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
3044
3045    /**
3046     * Flag indicating that the view is a root of a keyboard navigation cluster.
3047     *
3048     * @see #isKeyboardNavigationCluster()
3049     * @see #setKeyboardNavigationCluster(boolean)
3050     */
3051    private static final int PFLAG3_CLUSTER = 0x8000;
3052
3053    /**
3054     * Flag indicating that the view is autofilled
3055     *
3056     * @see #isAutofilled()
3057     * @see #setAutofilled(boolean)
3058     */
3059    private static final int PFLAG3_IS_AUTOFILLED = 0x10000;
3060
3061    /**
3062     * Indicates that the user is currently touching the screen.
3063     * Currently used for the tooltip positioning only.
3064     */
3065    private static final int PFLAG3_FINGER_DOWN = 0x20000;
3066
3067    /**
3068     * Flag indicating that this view is the default-focus view.
3069     *
3070     * @see #isFocusedByDefault()
3071     * @see #setFocusedByDefault(boolean)
3072     */
3073    private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000;
3074
3075    /**
3076     * Shift for the bits in {@link #mPrivateFlags3} related to the
3077     * "importantForAutofill" attribute.
3078     */
3079    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19;
3080
3081    /**
3082     * Mask for obtaining the bits which specify how to determine
3083     * whether a view is important for autofill.
3084     */
3085    static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO
3086            | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO
3087            | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
3088            | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS)
3089            << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
3090
3091    /**
3092     * Whether this view has rendered elements that overlap (see {@link
3093     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
3094     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
3095     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
3096     * determined by whatever {@link #hasOverlappingRendering()} returns.
3097     */
3098    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
3099
3100    /**
3101     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
3102     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
3103     */
3104    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
3105
3106    /**
3107     * Flag indicating that the view is temporarily detached from the parent view.
3108     *
3109     * @see #onStartTemporaryDetach()
3110     * @see #onFinishTemporaryDetach()
3111     */
3112    static final int PFLAG3_TEMPORARY_DETACH = 0x2000000;
3113
3114    /**
3115     * Flag indicating that the view does not wish to be revealed within its parent
3116     * hierarchy when it gains focus. Expressed in the negative since the historical
3117     * default behavior is to reveal on focus; this flag suppresses that behavior.
3118     *
3119     * @see #setRevealOnFocusHint(boolean)
3120     * @see #getRevealOnFocusHint()
3121     */
3122    private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000;
3123
3124    /**
3125     * Flag indicating that when layout is completed we should notify
3126     * that the view was entered for autofill purposes. To minimize
3127     * showing autofill for views not visible to the user we evaluate
3128     * user visibility which cannot be done until the view is laid out.
3129     */
3130    static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000;
3131
3132    /* End of masks for mPrivateFlags3 */
3133
3134    /**
3135     * Always allow a user to over-scroll this view, provided it is a
3136     * view that can scroll.
3137     *
3138     * @see #getOverScrollMode()
3139     * @see #setOverScrollMode(int)
3140     */
3141    public static final int OVER_SCROLL_ALWAYS = 0;
3142
3143    /**
3144     * Allow a user to over-scroll this view only if the content is large
3145     * enough to meaningfully scroll, provided it is a view that can scroll.
3146     *
3147     * @see #getOverScrollMode()
3148     * @see #setOverScrollMode(int)
3149     */
3150    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
3151
3152    /**
3153     * Never allow a user to over-scroll this view.
3154     *
3155     * @see #getOverScrollMode()
3156     * @see #setOverScrollMode(int)
3157     */
3158    public static final int OVER_SCROLL_NEVER = 2;
3159
3160    /**
3161     * Special constant for {@link #setSystemUiVisibility(int)}: View has
3162     * requested the system UI (status bar) to be visible (the default).
3163     *
3164     * @see #setSystemUiVisibility(int)
3165     */
3166    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
3167
3168    /**
3169     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
3170     * system UI to enter an unobtrusive "low profile" mode.
3171     *
3172     * <p>This is for use in games, book readers, video players, or any other
3173     * "immersive" application where the usual system chrome is deemed too distracting.
3174     *
3175     * <p>In low profile mode, the status bar and/or navigation icons may dim.
3176     *
3177     * @see #setSystemUiVisibility(int)
3178     */
3179    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
3180
3181    /**
3182     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
3183     * system navigation be temporarily hidden.
3184     *
3185     * <p>This is an even less obtrusive state than that called for by
3186     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
3187     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
3188     * those to disappear. This is useful (in conjunction with the
3189     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
3190     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
3191     * window flags) for displaying content using every last pixel on the display.
3192     *
3193     * <p>There is a limitation: because navigation controls are so important, the least user
3194     * interaction will cause them to reappear immediately.  When this happens, both
3195     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
3196     * so that both elements reappear at the same time.
3197     *
3198     * @see #setSystemUiVisibility(int)
3199     */
3200    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
3201
3202    /**
3203     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
3204     * into the normal fullscreen mode so that its content can take over the screen
3205     * while still allowing the user to interact with the application.
3206     *
3207     * <p>This has the same visual effect as
3208     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
3209     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
3210     * meaning that non-critical screen decorations (such as the status bar) will be
3211     * hidden while the user is in the View's window, focusing the experience on
3212     * that content.  Unlike the window flag, if you are using ActionBar in
3213     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3214     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
3215     * hide the action bar.
3216     *
3217     * <p>This approach to going fullscreen is best used over the window flag when
3218     * it is a transient state -- that is, the application does this at certain
3219     * points in its user interaction where it wants to allow the user to focus
3220     * on content, but not as a continuous state.  For situations where the application
3221     * would like to simply stay full screen the entire time (such as a game that
3222     * wants to take over the screen), the
3223     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
3224     * is usually a better approach.  The state set here will be removed by the system
3225     * in various situations (such as the user moving to another application) like
3226     * the other system UI states.
3227     *
3228     * <p>When using this flag, the application should provide some easy facility
3229     * for the user to go out of it.  A common example would be in an e-book
3230     * reader, where tapping on the screen brings back whatever screen and UI
3231     * decorations that had been hidden while the user was immersed in reading
3232     * the book.
3233     *
3234     * @see #setSystemUiVisibility(int)
3235     */
3236    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
3237
3238    /**
3239     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
3240     * flags, we would like a stable view of the content insets given to
3241     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
3242     * will always represent the worst case that the application can expect
3243     * as a continuous state.  In the stock Android UI this is the space for
3244     * the system bar, nav bar, and status bar, but not more transient elements
3245     * such as an input method.
3246     *
3247     * The stable layout your UI sees is based on the system UI modes you can
3248     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
3249     * then you will get a stable layout for changes of the
3250     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
3251     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
3252     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
3253     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
3254     * with a stable layout.  (Note that you should avoid using
3255     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
3256     *
3257     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
3258     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
3259     * then a hidden status bar will be considered a "stable" state for purposes
3260     * here.  This allows your UI to continually hide the status bar, while still
3261     * using the system UI flags to hide the action bar while still retaining
3262     * a stable layout.  Note that changing the window fullscreen flag will never
3263     * provide a stable layout for a clean transition.
3264     *
3265     * <p>If you are using ActionBar in
3266     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
3267     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
3268     * insets it adds to those given to the application.
3269     */
3270    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
3271
3272    /**
3273     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3274     * to be laid out as if it has requested
3275     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
3276     * allows it to avoid artifacts when switching in and out of that mode, at
3277     * the expense that some of its user interface may be covered by screen
3278     * decorations when they are shown.  You can perform layout of your inner
3279     * UI elements to account for the navigation system UI through the
3280     * {@link #fitSystemWindows(Rect)} method.
3281     */
3282    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
3283
3284    /**
3285     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
3286     * to be laid out as if it has requested
3287     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
3288     * allows it to avoid artifacts when switching in and out of that mode, at
3289     * the expense that some of its user interface may be covered by screen
3290     * decorations when they are shown.  You can perform layout of your inner
3291     * UI elements to account for non-fullscreen system UI through the
3292     * {@link #fitSystemWindows(Rect)} method.
3293     */
3294    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
3295
3296    /**
3297     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3298     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
3299     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
3300     * user interaction.
3301     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
3302     * has an effect when used in combination with that flag.</p>
3303     */
3304    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
3305
3306    /**
3307     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
3308     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
3309     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
3310     * experience while also hiding the system bars.  If this flag is not set,
3311     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
3312     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
3313     * if the user swipes from the top of the screen.
3314     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
3315     * system gestures, such as swiping from the top of the screen.  These transient system bars
3316     * will overlay app’s content, may have some degree of transparency, and will automatically
3317     * hide after a short timeout.
3318     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
3319     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
3320     * with one or both of those flags.</p>
3321     */
3322    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
3323
3324    /**
3325     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
3326     * is compatible with light status bar backgrounds.
3327     *
3328     * <p>For this to take effect, the window must request
3329     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3330     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3331     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
3332     *         FLAG_TRANSLUCENT_STATUS}.
3333     *
3334     * @see android.R.attr#windowLightStatusBar
3335     */
3336    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
3337
3338    /**
3339     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3340     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3341     */
3342    private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000;
3343
3344    /**
3345     * This flag was previously used for a private API. DO NOT reuse it for a public API as it might
3346     * trigger undefined behavior on older platforms with apps compiled against a new SDK.
3347     */
3348    private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000;
3349
3350    /**
3351     * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode
3352     * that is compatible with light navigation bar backgrounds.
3353     *
3354     * <p>For this to take effect, the window must request
3355     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
3356     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
3357     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION
3358     *         FLAG_TRANSLUCENT_NAVIGATION}.
3359     */
3360    public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010;
3361
3362    /**
3363     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
3364     */
3365    @Deprecated
3366    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
3367
3368    /**
3369     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
3370     */
3371    @Deprecated
3372    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
3373
3374    /**
3375     * @hide
3376     *
3377     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3378     * out of the public fields to keep the undefined bits out of the developer's way.
3379     *
3380     * Flag to make the status bar not expandable.  Unless you also
3381     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
3382     */
3383    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
3384
3385    /**
3386     * @hide
3387     *
3388     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3389     * out of the public fields to keep the undefined bits out of the developer's way.
3390     *
3391     * Flag to hide notification icons and scrolling ticker text.
3392     */
3393    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
3394
3395    /**
3396     * @hide
3397     *
3398     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3399     * out of the public fields to keep the undefined bits out of the developer's way.
3400     *
3401     * Flag to disable incoming notification alerts.  This will not block
3402     * icons, but it will block sound, vibrating and other visual or aural notifications.
3403     */
3404    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
3405
3406    /**
3407     * @hide
3408     *
3409     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3410     * out of the public fields to keep the undefined bits out of the developer's way.
3411     *
3412     * Flag to hide only the scrolling ticker.  Note that
3413     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
3414     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
3415     */
3416    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
3417
3418    /**
3419     * @hide
3420     *
3421     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3422     * out of the public fields to keep the undefined bits out of the developer's way.
3423     *
3424     * Flag to hide the center system info area.
3425     */
3426    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
3427
3428    /**
3429     * @hide
3430     *
3431     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3432     * out of the public fields to keep the undefined bits out of the developer's way.
3433     *
3434     * Flag to hide only the home button.  Don't use this
3435     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3436     */
3437    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
3438
3439    /**
3440     * @hide
3441     *
3442     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3443     * out of the public fields to keep the undefined bits out of the developer's way.
3444     *
3445     * Flag to hide only the back button. Don't use this
3446     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3447     */
3448    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
3449
3450    /**
3451     * @hide
3452     *
3453     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3454     * out of the public fields to keep the undefined bits out of the developer's way.
3455     *
3456     * Flag to hide only the clock.  You might use this if your activity has
3457     * its own clock making the status bar's clock redundant.
3458     */
3459    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
3460
3461    /**
3462     * @hide
3463     *
3464     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3465     * out of the public fields to keep the undefined bits out of the developer's way.
3466     *
3467     * Flag to hide only the recent apps button. Don't use this
3468     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3469     */
3470    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
3471
3472    /**
3473     * @hide
3474     *
3475     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3476     * out of the public fields to keep the undefined bits out of the developer's way.
3477     *
3478     * Flag to disable the global search gesture. Don't use this
3479     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
3480     */
3481    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
3482
3483    /**
3484     * @hide
3485     *
3486     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3487     * out of the public fields to keep the undefined bits out of the developer's way.
3488     *
3489     * Flag to specify that the status bar is displayed in transient mode.
3490     */
3491    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
3492
3493    /**
3494     * @hide
3495     *
3496     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3497     * out of the public fields to keep the undefined bits out of the developer's way.
3498     *
3499     * Flag to specify that the navigation bar is displayed in transient mode.
3500     */
3501    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
3502
3503    /**
3504     * @hide
3505     *
3506     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3507     * out of the public fields to keep the undefined bits out of the developer's way.
3508     *
3509     * Flag to specify that the hidden status bar would like to be shown.
3510     */
3511    public static final int STATUS_BAR_UNHIDE = 0x10000000;
3512
3513    /**
3514     * @hide
3515     *
3516     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3517     * out of the public fields to keep the undefined bits out of the developer's way.
3518     *
3519     * Flag to specify that the hidden navigation bar would like to be shown.
3520     */
3521    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3522
3523    /**
3524     * @hide
3525     *
3526     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3527     * out of the public fields to keep the undefined bits out of the developer's way.
3528     *
3529     * Flag to specify that the status bar is displayed in translucent mode.
3530     */
3531    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3532
3533    /**
3534     * @hide
3535     *
3536     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3537     * out of the public fields to keep the undefined bits out of the developer's way.
3538     *
3539     * Flag to specify that the navigation bar is displayed in translucent mode.
3540     */
3541    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3542
3543    /**
3544     * @hide
3545     *
3546     * Makes navigation bar transparent (but not the status bar).
3547     */
3548    public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000;
3549
3550    /**
3551     * @hide
3552     *
3553     * Makes status bar transparent (but not the navigation bar).
3554     */
3555    public static final int STATUS_BAR_TRANSPARENT = 0x00000008;
3556
3557    /**
3558     * @hide
3559     *
3560     * Makes both status bar and navigation bar transparent.
3561     */
3562    public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT
3563            | STATUS_BAR_TRANSPARENT;
3564
3565    /**
3566     * @hide
3567     */
3568    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7;
3569
3570    /**
3571     * These are the system UI flags that can be cleared by events outside
3572     * of an application.  Currently this is just the ability to tap on the
3573     * screen while hiding the navigation bar to have it return.
3574     * @hide
3575     */
3576    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3577            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3578            | SYSTEM_UI_FLAG_FULLSCREEN;
3579
3580    /**
3581     * Flags that can impact the layout in relation to system UI.
3582     */
3583    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3584            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3585            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3586
3587    /** @hide */
3588    @IntDef(flag = true,
3589            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3590    @Retention(RetentionPolicy.SOURCE)
3591    public @interface FindViewFlags {}
3592
3593    /**
3594     * Find views that render the specified text.
3595     *
3596     * @see #findViewsWithText(ArrayList, CharSequence, int)
3597     */
3598    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3599
3600    /**
3601     * Find find views that contain the specified content description.
3602     *
3603     * @see #findViewsWithText(ArrayList, CharSequence, int)
3604     */
3605    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3606
3607    /**
3608     * Find views that contain {@link AccessibilityNodeProvider}. Such
3609     * a View is a root of virtual view hierarchy and may contain the searched
3610     * text. If this flag is set Views with providers are automatically
3611     * added and it is a responsibility of the client to call the APIs of
3612     * the provider to determine whether the virtual tree rooted at this View
3613     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3614     * representing the virtual views with this text.
3615     *
3616     * @see #findViewsWithText(ArrayList, CharSequence, int)
3617     *
3618     * @hide
3619     */
3620    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3621
3622    /**
3623     * The undefined cursor position.
3624     *
3625     * @hide
3626     */
3627    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3628
3629    /**
3630     * Indicates that the screen has changed state and is now off.
3631     *
3632     * @see #onScreenStateChanged(int)
3633     */
3634    public static final int SCREEN_STATE_OFF = 0x0;
3635
3636    /**
3637     * Indicates that the screen has changed state and is now on.
3638     *
3639     * @see #onScreenStateChanged(int)
3640     */
3641    public static final int SCREEN_STATE_ON = 0x1;
3642
3643    /**
3644     * Indicates no axis of view scrolling.
3645     */
3646    public static final int SCROLL_AXIS_NONE = 0;
3647
3648    /**
3649     * Indicates scrolling along the horizontal axis.
3650     */
3651    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3652
3653    /**
3654     * Indicates scrolling along the vertical axis.
3655     */
3656    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3657
3658    /**
3659     * Controls the over-scroll mode for this view.
3660     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3661     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3662     * and {@link #OVER_SCROLL_NEVER}.
3663     */
3664    private int mOverScrollMode;
3665
3666    /**
3667     * The parent this view is attached to.
3668     * {@hide}
3669     *
3670     * @see #getParent()
3671     */
3672    protected ViewParent mParent;
3673
3674    /**
3675     * {@hide}
3676     */
3677    AttachInfo mAttachInfo;
3678
3679    /**
3680     * {@hide}
3681     */
3682    @ViewDebug.ExportedProperty(flagMapping = {
3683        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3684                name = "FORCE_LAYOUT"),
3685        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3686                name = "LAYOUT_REQUIRED"),
3687        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3688            name = "DRAWING_CACHE_INVALID", outputIf = false),
3689        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3690        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3691        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3692        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3693    }, formatToHexString = true)
3694
3695    /* @hide */
3696    public int mPrivateFlags;
3697    int mPrivateFlags2;
3698    int mPrivateFlags3;
3699
3700    /**
3701     * This view's request for the visibility of the status bar.
3702     * @hide
3703     */
3704    @ViewDebug.ExportedProperty(flagMapping = {
3705        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3706                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3707                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3708        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3709                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3710                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3711        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3712                                equals = SYSTEM_UI_FLAG_VISIBLE,
3713                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3714    }, formatToHexString = true)
3715    int mSystemUiVisibility;
3716
3717    /**
3718     * Reference count for transient state.
3719     * @see #setHasTransientState(boolean)
3720     */
3721    int mTransientStateCount = 0;
3722
3723    /**
3724     * Count of how many windows this view has been attached to.
3725     */
3726    int mWindowAttachCount;
3727
3728    /**
3729     * The layout parameters associated with this view and used by the parent
3730     * {@link android.view.ViewGroup} to determine how this view should be
3731     * laid out.
3732     * {@hide}
3733     */
3734    protected ViewGroup.LayoutParams mLayoutParams;
3735
3736    /**
3737     * The view flags hold various views states.
3738     * {@hide}
3739     */
3740    @ViewDebug.ExportedProperty(formatToHexString = true)
3741    int mViewFlags;
3742
3743    static class TransformationInfo {
3744        /**
3745         * The transform matrix for the View. This transform is calculated internally
3746         * based on the translation, rotation, and scale properties.
3747         *
3748         * Do *not* use this variable directly; instead call getMatrix(), which will
3749         * load the value from the View's RenderNode.
3750         */
3751        private final Matrix mMatrix = new Matrix();
3752
3753        /**
3754         * The inverse transform matrix for the View. This transform is calculated
3755         * internally based on the translation, rotation, and scale properties.
3756         *
3757         * Do *not* use this variable directly; instead call getInverseMatrix(),
3758         * which will load the value from the View's RenderNode.
3759         */
3760        private Matrix mInverseMatrix;
3761
3762        /**
3763         * The opacity of the View. This is a value from 0 to 1, where 0 means
3764         * completely transparent and 1 means completely opaque.
3765         */
3766        @ViewDebug.ExportedProperty
3767        float mAlpha = 1f;
3768
3769        /**
3770         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3771         * property only used by transitions, which is composited with the other alpha
3772         * values to calculate the final visual alpha value.
3773         */
3774        float mTransitionAlpha = 1f;
3775    }
3776
3777    /** @hide */
3778    public TransformationInfo mTransformationInfo;
3779
3780    /**
3781     * Current clip bounds. to which all drawing of this view are constrained.
3782     */
3783    Rect mClipBounds = null;
3784
3785    private boolean mLastIsOpaque;
3786
3787    /**
3788     * The distance in pixels from the left edge of this view's parent
3789     * to the left edge of this view.
3790     * {@hide}
3791     */
3792    @ViewDebug.ExportedProperty(category = "layout")
3793    protected int mLeft;
3794    /**
3795     * The distance in pixels from the left edge of this view's parent
3796     * to the right edge of this view.
3797     * {@hide}
3798     */
3799    @ViewDebug.ExportedProperty(category = "layout")
3800    protected int mRight;
3801    /**
3802     * The distance in pixels from the top edge of this view's parent
3803     * to the top edge of this view.
3804     * {@hide}
3805     */
3806    @ViewDebug.ExportedProperty(category = "layout")
3807    protected int mTop;
3808    /**
3809     * The distance in pixels from the top edge of this view's parent
3810     * to the bottom edge of this view.
3811     * {@hide}
3812     */
3813    @ViewDebug.ExportedProperty(category = "layout")
3814    protected int mBottom;
3815
3816    /**
3817     * The offset, in pixels, by which the content of this view is scrolled
3818     * horizontally.
3819     * {@hide}
3820     */
3821    @ViewDebug.ExportedProperty(category = "scrolling")
3822    protected int mScrollX;
3823    /**
3824     * The offset, in pixels, by which the content of this view is scrolled
3825     * vertically.
3826     * {@hide}
3827     */
3828    @ViewDebug.ExportedProperty(category = "scrolling")
3829    protected int mScrollY;
3830
3831    /**
3832     * The left padding in pixels, that is the distance in pixels between the
3833     * left edge of this view and the left edge of its content.
3834     * {@hide}
3835     */
3836    @ViewDebug.ExportedProperty(category = "padding")
3837    protected int mPaddingLeft = 0;
3838    /**
3839     * The right padding in pixels, that is the distance in pixels between the
3840     * right edge of this view and the right edge of its content.
3841     * {@hide}
3842     */
3843    @ViewDebug.ExportedProperty(category = "padding")
3844    protected int mPaddingRight = 0;
3845    /**
3846     * The top padding in pixels, that is the distance in pixels between the
3847     * top edge of this view and the top edge of its content.
3848     * {@hide}
3849     */
3850    @ViewDebug.ExportedProperty(category = "padding")
3851    protected int mPaddingTop;
3852    /**
3853     * The bottom padding in pixels, that is the distance in pixels between the
3854     * bottom edge of this view and the bottom edge of its content.
3855     * {@hide}
3856     */
3857    @ViewDebug.ExportedProperty(category = "padding")
3858    protected int mPaddingBottom;
3859
3860    /**
3861     * The layout insets in pixels, that is the distance in pixels between the
3862     * visible edges of this view its bounds.
3863     */
3864    private Insets mLayoutInsets;
3865
3866    /**
3867     * Briefly describes the view and is primarily used for accessibility support.
3868     */
3869    private CharSequence mContentDescription;
3870
3871    /**
3872     * Specifies the id of a view for which this view serves as a label for
3873     * accessibility purposes.
3874     */
3875    private int mLabelForId = View.NO_ID;
3876
3877    /**
3878     * Predicate for matching labeled view id with its label for
3879     * accessibility purposes.
3880     */
3881    private MatchLabelForPredicate mMatchLabelForPredicate;
3882
3883    /**
3884     * Specifies a view before which this one is visited in accessibility traversal.
3885     */
3886    private int mAccessibilityTraversalBeforeId = NO_ID;
3887
3888    /**
3889     * Specifies a view after which this one is visited in accessibility traversal.
3890     */
3891    private int mAccessibilityTraversalAfterId = NO_ID;
3892
3893    /**
3894     * Predicate for matching a view by its id.
3895     */
3896    private MatchIdPredicate mMatchIdPredicate;
3897
3898    /**
3899     * Cache the paddingRight set by the user to append to the scrollbar's size.
3900     *
3901     * @hide
3902     */
3903    @ViewDebug.ExportedProperty(category = "padding")
3904    protected int mUserPaddingRight;
3905
3906    /**
3907     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3908     *
3909     * @hide
3910     */
3911    @ViewDebug.ExportedProperty(category = "padding")
3912    protected int mUserPaddingBottom;
3913
3914    /**
3915     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3916     *
3917     * @hide
3918     */
3919    @ViewDebug.ExportedProperty(category = "padding")
3920    protected int mUserPaddingLeft;
3921
3922    /**
3923     * Cache the paddingStart set by the user to append to the scrollbar's size.
3924     *
3925     */
3926    @ViewDebug.ExportedProperty(category = "padding")
3927    int mUserPaddingStart;
3928
3929    /**
3930     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3931     *
3932     */
3933    @ViewDebug.ExportedProperty(category = "padding")
3934    int mUserPaddingEnd;
3935
3936    /**
3937     * Cache initial left padding.
3938     *
3939     * @hide
3940     */
3941    int mUserPaddingLeftInitial;
3942
3943    /**
3944     * Cache initial right padding.
3945     *
3946     * @hide
3947     */
3948    int mUserPaddingRightInitial;
3949
3950    /**
3951     * Default undefined padding
3952     */
3953    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3954
3955    /**
3956     * Cache if a left padding has been defined
3957     */
3958    private boolean mLeftPaddingDefined = false;
3959
3960    /**
3961     * Cache if a right padding has been defined
3962     */
3963    private boolean mRightPaddingDefined = false;
3964
3965    /**
3966     * @hide
3967     */
3968    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3969    /**
3970     * @hide
3971     */
3972    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3973
3974    private LongSparseLongArray mMeasureCache;
3975
3976    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3977    private Drawable mBackground;
3978    private TintInfo mBackgroundTint;
3979
3980    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3981    private ForegroundInfo mForegroundInfo;
3982
3983    private Drawable mScrollIndicatorDrawable;
3984
3985    /**
3986     * RenderNode used for backgrounds.
3987     * <p>
3988     * When non-null and valid, this is expected to contain an up-to-date copy
3989     * of the background drawable. It is cleared on temporary detach, and reset
3990     * on cleanup.
3991     */
3992    private RenderNode mBackgroundRenderNode;
3993
3994    private int mBackgroundResource;
3995    private boolean mBackgroundSizeChanged;
3996
3997    /** The default focus highlight.
3998     * @see #mDefaultFocusHighlightEnabled
3999     * @see Drawable#hasFocusStateSpecified()
4000     */
4001    private Drawable mDefaultFocusHighlight;
4002    private Drawable mDefaultFocusHighlightCache;
4003    private boolean mDefaultFocusHighlightSizeChanged;
4004    /**
4005     * True if the default focus highlight is needed on the target device.
4006     */
4007    private static boolean sUseDefaultFocusHighlight;
4008
4009    private String mTransitionName;
4010
4011    static class TintInfo {
4012        ColorStateList mTintList;
4013        PorterDuff.Mode mTintMode;
4014        boolean mHasTintMode;
4015        boolean mHasTintList;
4016    }
4017
4018    private static class ForegroundInfo {
4019        private Drawable mDrawable;
4020        private TintInfo mTintInfo;
4021        private int mGravity = Gravity.FILL;
4022        private boolean mInsidePadding = true;
4023        private boolean mBoundsChanged = true;
4024        private final Rect mSelfBounds = new Rect();
4025        private final Rect mOverlayBounds = new Rect();
4026    }
4027
4028    static class ListenerInfo {
4029        /**
4030         * Listener used to dispatch focus change events.
4031         * This field should be made private, so it is hidden from the SDK.
4032         * {@hide}
4033         */
4034        protected OnFocusChangeListener mOnFocusChangeListener;
4035
4036        /**
4037         * Listeners for layout change events.
4038         */
4039        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
4040
4041        protected OnScrollChangeListener mOnScrollChangeListener;
4042
4043        /**
4044         * Listeners for attach events.
4045         */
4046        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
4047
4048        /**
4049         * Listener used to dispatch click events.
4050         * This field should be made private, so it is hidden from the SDK.
4051         * {@hide}
4052         */
4053        public OnClickListener mOnClickListener;
4054
4055        /**
4056         * Listener used to dispatch long click events.
4057         * This field should be made private, so it is hidden from the SDK.
4058         * {@hide}
4059         */
4060        protected OnLongClickListener mOnLongClickListener;
4061
4062        /**
4063         * Listener used to dispatch context click events. This field should be made private, so it
4064         * is hidden from the SDK.
4065         * {@hide}
4066         */
4067        protected OnContextClickListener mOnContextClickListener;
4068
4069        /**
4070         * Listener used to build the context menu.
4071         * This field should be made private, so it is hidden from the SDK.
4072         * {@hide}
4073         */
4074        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
4075
4076        private OnKeyListener mOnKeyListener;
4077
4078        private OnTouchListener mOnTouchListener;
4079
4080        private OnHoverListener mOnHoverListener;
4081
4082        private OnGenericMotionListener mOnGenericMotionListener;
4083
4084        private OnDragListener mOnDragListener;
4085
4086        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
4087
4088        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
4089
4090        OnCapturedPointerListener mOnCapturedPointerListener;
4091    }
4092
4093    ListenerInfo mListenerInfo;
4094
4095    private static class TooltipInfo {
4096        /**
4097         * Text to be displayed in a tooltip popup.
4098         */
4099        @Nullable
4100        CharSequence mTooltipText;
4101
4102        /**
4103         * View-relative position of the tooltip anchor point.
4104         */
4105        int mAnchorX;
4106        int mAnchorY;
4107
4108        /**
4109         * The tooltip popup.
4110         */
4111        @Nullable
4112        TooltipPopup mTooltipPopup;
4113
4114        /**
4115         * Set to true if the tooltip was shown as a result of a long click.
4116         */
4117        boolean mTooltipFromLongClick;
4118
4119        /**
4120         * Keep these Runnables so that they can be used to reschedule.
4121         */
4122        Runnable mShowTooltipRunnable;
4123        Runnable mHideTooltipRunnable;
4124    }
4125
4126    TooltipInfo mTooltipInfo;
4127
4128    // Temporary values used to hold (x,y) coordinates when delegating from the
4129    // two-arg performLongClick() method to the legacy no-arg version.
4130    private float mLongClickX = Float.NaN;
4131    private float mLongClickY = Float.NaN;
4132
4133    /**
4134     * The application environment this view lives in.
4135     * This field should be made private, so it is hidden from the SDK.
4136     * {@hide}
4137     */
4138    @ViewDebug.ExportedProperty(deepExport = true)
4139    protected Context mContext;
4140
4141    private final Resources mResources;
4142
4143    private ScrollabilityCache mScrollCache;
4144
4145    private int[] mDrawableState = null;
4146
4147    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
4148
4149    /**
4150     * Animator that automatically runs based on state changes.
4151     */
4152    private StateListAnimator mStateListAnimator;
4153
4154    /**
4155     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
4156     * the user may specify which view to go to next.
4157     */
4158    private int mNextFocusLeftId = View.NO_ID;
4159
4160    /**
4161     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
4162     * the user may specify which view to go to next.
4163     */
4164    private int mNextFocusRightId = View.NO_ID;
4165
4166    /**
4167     * When this view has focus and the next focus is {@link #FOCUS_UP},
4168     * the user may specify which view to go to next.
4169     */
4170    private int mNextFocusUpId = View.NO_ID;
4171
4172    /**
4173     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
4174     * the user may specify which view to go to next.
4175     */
4176    private int mNextFocusDownId = View.NO_ID;
4177
4178    /**
4179     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
4180     * the user may specify which view to go to next.
4181     */
4182    int mNextFocusForwardId = View.NO_ID;
4183
4184    /**
4185     * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction.
4186     *
4187     * @see #findUserSetNextKeyboardNavigationCluster(View, int)
4188     */
4189    int mNextClusterForwardId = View.NO_ID;
4190
4191    /**
4192     * Whether this View should use a default focus highlight when it gets focused but doesn't
4193     * have {@link android.R.attr#state_focused} defined in its background.
4194     */
4195    boolean mDefaultFocusHighlightEnabled = true;
4196
4197    private CheckForLongPress mPendingCheckForLongPress;
4198    private CheckForTap mPendingCheckForTap = null;
4199    private PerformClick mPerformClick;
4200    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
4201
4202    private UnsetPressedState mUnsetPressedState;
4203
4204    /**
4205     * Whether the long press's action has been invoked.  The tap's action is invoked on the
4206     * up event while a long press is invoked as soon as the long press duration is reached, so
4207     * a long press could be performed before the tap is checked, in which case the tap's action
4208     * should not be invoked.
4209     */
4210    private boolean mHasPerformedLongPress;
4211
4212    /**
4213     * Whether a context click button is currently pressed down. This is true when the stylus is
4214     * touching the screen and the primary button has been pressed, or if a mouse's right button is
4215     * pressed. This is false once the button is released or if the stylus has been lifted.
4216     */
4217    private boolean mInContextButtonPress;
4218
4219    /**
4220     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
4221     * true after a stylus button press has occured, when the next up event should not be recognized
4222     * as a tap.
4223     */
4224    private boolean mIgnoreNextUpEvent;
4225
4226    /**
4227     * The minimum height of the view. We'll try our best to have the height
4228     * of this view to at least this amount.
4229     */
4230    @ViewDebug.ExportedProperty(category = "measurement")
4231    private int mMinHeight;
4232
4233    /**
4234     * The minimum width of the view. We'll try our best to have the width
4235     * of this view to at least this amount.
4236     */
4237    @ViewDebug.ExportedProperty(category = "measurement")
4238    private int mMinWidth;
4239
4240    /**
4241     * The delegate to handle touch events that are physically in this view
4242     * but should be handled by another view.
4243     */
4244    private TouchDelegate mTouchDelegate = null;
4245
4246    /**
4247     * Solid color to use as a background when creating the drawing cache. Enables
4248     * the cache to use 16 bit bitmaps instead of 32 bit.
4249     */
4250    private int mDrawingCacheBackgroundColor = 0;
4251
4252    /**
4253     * Special tree observer used when mAttachInfo is null.
4254     */
4255    private ViewTreeObserver mFloatingTreeObserver;
4256
4257    /**
4258     * Cache the touch slop from the context that created the view.
4259     */
4260    private int mTouchSlop;
4261
4262    /**
4263     * Object that handles automatic animation of view properties.
4264     */
4265    private ViewPropertyAnimator mAnimator = null;
4266
4267    /**
4268     * List of registered FrameMetricsObservers.
4269     */
4270    private ArrayList<FrameMetricsObserver> mFrameMetricsObservers;
4271
4272    /**
4273     * Flag indicating that a drag can cross window boundaries.  When
4274     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4275     * with this flag set, all visible applications with targetSdkVersion >=
4276     * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate
4277     * in the drag operation and receive the dragged content.
4278     *
4279     * <p>If this is the only flag set, then the drag recipient will only have access to text data
4280     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
4281     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p>
4282     */
4283    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
4284
4285    /**
4286     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4287     * request read access to the content URI(s) contained in the {@link ClipData} object.
4288     * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION
4289     */
4290    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
4291
4292    /**
4293     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
4294     * request write access to the content URI(s) contained in the {@link ClipData} object.
4295     * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION
4296     */
4297    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
4298
4299    /**
4300     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4301     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
4302     * reboots until explicitly revoked with
4303     * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}.
4304     * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
4305     */
4306    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
4307            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
4308
4309    /**
4310     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
4311     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
4312     * match against the original granted URI.
4313     * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
4314     */
4315    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
4316            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
4317
4318    /**
4319     * Flag indicating that the drag shadow will be opaque.  When
4320     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called
4321     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
4322     */
4323    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
4324
4325    /**
4326     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
4327     */
4328    private float mVerticalScrollFactor;
4329
4330    /**
4331     * Position of the vertical scroll bar.
4332     */
4333    private int mVerticalScrollbarPosition;
4334
4335    /**
4336     * Position the scroll bar at the default position as determined by the system.
4337     */
4338    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
4339
4340    /**
4341     * Position the scroll bar along the left edge.
4342     */
4343    public static final int SCROLLBAR_POSITION_LEFT = 1;
4344
4345    /**
4346     * Position the scroll bar along the right edge.
4347     */
4348    public static final int SCROLLBAR_POSITION_RIGHT = 2;
4349
4350    /**
4351     * Indicates that the view does not have a layer.
4352     *
4353     * @see #getLayerType()
4354     * @see #setLayerType(int, android.graphics.Paint)
4355     * @see #LAYER_TYPE_SOFTWARE
4356     * @see #LAYER_TYPE_HARDWARE
4357     */
4358    public static final int LAYER_TYPE_NONE = 0;
4359
4360    /**
4361     * <p>Indicates that the view has a software layer. A software layer is backed
4362     * by a bitmap and causes the view to be rendered using Android's software
4363     * rendering pipeline, even if hardware acceleration is enabled.</p>
4364     *
4365     * <p>Software layers have various usages:</p>
4366     * <p>When the application is not using hardware acceleration, a software layer
4367     * is useful to apply a specific color filter and/or blending mode and/or
4368     * translucency to a view and all its children.</p>
4369     * <p>When the application is using hardware acceleration, a software layer
4370     * is useful to render drawing primitives not supported by the hardware
4371     * accelerated pipeline. It can also be used to cache a complex view tree
4372     * into a texture and reduce the complexity of drawing operations. For instance,
4373     * when animating a complex view tree with a translation, a software layer can
4374     * be used to render the view tree only once.</p>
4375     * <p>Software layers should be avoided when the affected view tree updates
4376     * often. Every update will require to re-render the software layer, which can
4377     * potentially be slow (particularly when hardware acceleration is turned on
4378     * since the layer will have to be uploaded into a hardware texture after every
4379     * update.)</p>
4380     *
4381     * @see #getLayerType()
4382     * @see #setLayerType(int, android.graphics.Paint)
4383     * @see #LAYER_TYPE_NONE
4384     * @see #LAYER_TYPE_HARDWARE
4385     */
4386    public static final int LAYER_TYPE_SOFTWARE = 1;
4387
4388    /**
4389     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
4390     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
4391     * OpenGL hardware) and causes the view to be rendered using Android's hardware
4392     * rendering pipeline, but only if hardware acceleration is turned on for the
4393     * view hierarchy. When hardware acceleration is turned off, hardware layers
4394     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
4395     *
4396     * <p>A hardware layer is useful to apply a specific color filter and/or
4397     * blending mode and/or translucency to a view and all its children.</p>
4398     * <p>A hardware layer can be used to cache a complex view tree into a
4399     * texture and reduce the complexity of drawing operations. For instance,
4400     * when animating a complex view tree with a translation, a hardware layer can
4401     * be used to render the view tree only once.</p>
4402     * <p>A hardware layer can also be used to increase the rendering quality when
4403     * rotation transformations are applied on a view. It can also be used to
4404     * prevent potential clipping issues when applying 3D transforms on a view.</p>
4405     *
4406     * @see #getLayerType()
4407     * @see #setLayerType(int, android.graphics.Paint)
4408     * @see #LAYER_TYPE_NONE
4409     * @see #LAYER_TYPE_SOFTWARE
4410     */
4411    public static final int LAYER_TYPE_HARDWARE = 2;
4412
4413    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
4414            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
4415            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
4416            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
4417    })
4418    int mLayerType = LAYER_TYPE_NONE;
4419    Paint mLayerPaint;
4420
4421    /**
4422     * Set to true when drawing cache is enabled and cannot be created.
4423     *
4424     * @hide
4425     */
4426    public boolean mCachingFailed;
4427    private Bitmap mDrawingCache;
4428    private Bitmap mUnscaledDrawingCache;
4429
4430    /**
4431     * RenderNode holding View properties, potentially holding a DisplayList of View content.
4432     * <p>
4433     * When non-null and valid, this is expected to contain an up-to-date copy
4434     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
4435     * cleanup.
4436     */
4437    final RenderNode mRenderNode;
4438
4439    /**
4440     * Set to true when the view is sending hover accessibility events because it
4441     * is the innermost hovered view.
4442     */
4443    private boolean mSendingHoverAccessibilityEvents;
4444
4445    /**
4446     * Delegate for injecting accessibility functionality.
4447     */
4448    AccessibilityDelegate mAccessibilityDelegate;
4449
4450    /**
4451     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
4452     * and add/remove objects to/from the overlay directly through the Overlay methods.
4453     */
4454    ViewOverlay mOverlay;
4455
4456    /**
4457     * The currently active parent view for receiving delegated nested scrolling events.
4458     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
4459     * by {@link #stopNestedScroll()} at the same point where we clear
4460     * requestDisallowInterceptTouchEvent.
4461     */
4462    private ViewParent mNestedScrollingParent;
4463
4464    /**
4465     * Consistency verifier for debugging purposes.
4466     * @hide
4467     */
4468    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
4469            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
4470                    new InputEventConsistencyVerifier(this, 0) : null;
4471
4472    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
4473
4474    private int[] mTempNestedScrollConsumed;
4475
4476    /**
4477     * An overlay is going to draw this View instead of being drawn as part of this
4478     * View's parent. mGhostView is the View in the Overlay that must be invalidated
4479     * when this view is invalidated.
4480     */
4481    GhostView mGhostView;
4482
4483    /**
4484     * Holds pairs of adjacent attribute data: attribute name followed by its value.
4485     * @hide
4486     */
4487    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
4488    public String[] mAttributes;
4489
4490    /**
4491     * Maps a Resource id to its name.
4492     */
4493    private static SparseArray<String> mAttributeMap;
4494
4495    /**
4496     * Queue of pending runnables. Used to postpone calls to post() until this
4497     * view is attached and has a handler.
4498     */
4499    private HandlerActionQueue mRunQueue;
4500
4501    /**
4502     * The pointer icon when the mouse hovers on this view. The default is null.
4503     */
4504    private PointerIcon mPointerIcon;
4505
4506    /**
4507     * @hide
4508     */
4509    String mStartActivityRequestWho;
4510
4511    @Nullable
4512    private RoundScrollbarRenderer mRoundScrollbarRenderer;
4513
4514    /** Used to delay visibility updates sent to the autofill manager */
4515    private Handler mVisibilityChangeForAutofillHandler;
4516
4517    /**
4518     * Simple constructor to use when creating a view from code.
4519     *
4520     * @param context The Context the view is running in, through which it can
4521     *        access the current theme, resources, etc.
4522     */
4523    public View(Context context) {
4524        mContext = context;
4525        mResources = context != null ? context.getResources() : null;
4526        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
4527        // Set some flags defaults
4528        mPrivateFlags2 =
4529                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
4530                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
4531                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
4532                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
4533                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
4534                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
4535        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
4536        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
4537        mUserPaddingStart = UNDEFINED_PADDING;
4538        mUserPaddingEnd = UNDEFINED_PADDING;
4539        mRenderNode = RenderNode.create(getClass().getName(), this);
4540
4541        if (!sCompatibilityDone && context != null) {
4542            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4543
4544            // Older apps may need this compatibility hack for measurement.
4545            sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
4546
4547            // Older apps expect onMeasure() to always be called on a layout pass, regardless
4548            // of whether a layout was requested on that View.
4549            sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT;
4550
4551            Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M;
4552            Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O;
4553
4554            // In M and newer, our widgets can pass a "hint" value in the size
4555            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
4556            // know what the expected parent size is going to be, so e.g. list items can size
4557            // themselves at 1/3 the size of their container. It breaks older apps though,
4558            // specifically apps that use some popular open source libraries.
4559            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M;
4560
4561            // Old versions of the platform would give different results from
4562            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
4563            // modes, so we always need to run an additional EXACTLY pass.
4564            sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M;
4565
4566            // Prior to N, layout params could change without requiring a
4567            // subsequent call to setLayoutParams() and they would usually
4568            // work. Partial layout breaks this assumption.
4569            sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M;
4570
4571            // Prior to N, TextureView would silently ignore calls to setBackground/setForeground.
4572            // On N+, we throw, but that breaks compatibility with apps that use these methods.
4573            sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M;
4574
4575            // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs
4576            // in apps so we target check it to avoid breaking existing apps.
4577            sPreserveMarginParamsInLayoutParamConversion =
4578                    targetSdkVersion >= Build.VERSION_CODES.N;
4579
4580            sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N;
4581
4582            sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O;
4583
4584            sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O;
4585
4586            sUseDefaultFocusHighlight = context.getResources().getBoolean(
4587                    com.android.internal.R.bool.config_useDefaultFocusHighlight);
4588
4589            sCompatibilityDone = true;
4590        }
4591    }
4592
4593    /**
4594     * Constructor that is called when inflating a view from XML. This is called
4595     * when a view is being constructed from an XML file, supplying attributes
4596     * that were specified in the XML file. This version uses a default style of
4597     * 0, so the only attribute values applied are those in the Context's Theme
4598     * and the given AttributeSet.
4599     *
4600     * <p>
4601     * The method onFinishInflate() will be called after all children have been
4602     * added.
4603     *
4604     * @param context The Context the view is running in, through which it can
4605     *        access the current theme, resources, etc.
4606     * @param attrs The attributes of the XML tag that is inflating the view.
4607     * @see #View(Context, AttributeSet, int)
4608     */
4609    public View(Context context, @Nullable AttributeSet attrs) {
4610        this(context, attrs, 0);
4611    }
4612
4613    /**
4614     * Perform inflation from XML and apply a class-specific base style from a
4615     * theme attribute. This constructor of View allows subclasses to use their
4616     * own base style when they are inflating. For example, a Button class's
4617     * constructor would call this version of the super class constructor and
4618     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
4619     * allows the theme's button style to modify all of the base view attributes
4620     * (in particular its background) as well as the Button class's attributes.
4621     *
4622     * @param context The Context the view is running in, through which it can
4623     *        access the current theme, resources, etc.
4624     * @param attrs The attributes of the XML tag that is inflating the view.
4625     * @param defStyleAttr An attribute in the current theme that contains a
4626     *        reference to a style resource that supplies default values for
4627     *        the view. Can be 0 to not look for defaults.
4628     * @see #View(Context, AttributeSet)
4629     */
4630    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4631        this(context, attrs, defStyleAttr, 0);
4632    }
4633
4634    /**
4635     * Perform inflation from XML and apply a class-specific base style from a
4636     * theme attribute or style resource. This constructor of View allows
4637     * subclasses to use their own base style when they are inflating.
4638     * <p>
4639     * When determining the final value of a particular attribute, there are
4640     * four inputs that come into play:
4641     * <ol>
4642     * <li>Any attribute values in the given AttributeSet.
4643     * <li>The style resource specified in the AttributeSet (named "style").
4644     * <li>The default style specified by <var>defStyleAttr</var>.
4645     * <li>The default style specified by <var>defStyleRes</var>.
4646     * <li>The base values in this theme.
4647     * </ol>
4648     * <p>
4649     * Each of these inputs is considered in-order, with the first listed taking
4650     * precedence over the following ones. In other words, if in the
4651     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4652     * , then the button's text will <em>always</em> be black, regardless of
4653     * what is specified in any of the styles.
4654     *
4655     * @param context The Context the view is running in, through which it can
4656     *        access the current theme, resources, etc.
4657     * @param attrs The attributes of the XML tag that is inflating the view.
4658     * @param defStyleAttr An attribute in the current theme that contains a
4659     *        reference to a style resource that supplies default values for
4660     *        the view. Can be 0 to not look for defaults.
4661     * @param defStyleRes A resource identifier of a style resource that
4662     *        supplies default values for the view, used only if
4663     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4664     *        to not look for defaults.
4665     * @see #View(Context, AttributeSet, int)
4666     */
4667    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4668        this(context);
4669
4670        final TypedArray a = context.obtainStyledAttributes(
4671                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4672
4673        if (mDebugViewAttributes) {
4674            saveAttributeData(attrs, a);
4675        }
4676
4677        Drawable background = null;
4678
4679        int leftPadding = -1;
4680        int topPadding = -1;
4681        int rightPadding = -1;
4682        int bottomPadding = -1;
4683        int startPadding = UNDEFINED_PADDING;
4684        int endPadding = UNDEFINED_PADDING;
4685
4686        int padding = -1;
4687        int paddingHorizontal = -1;
4688        int paddingVertical = -1;
4689
4690        int viewFlagValues = 0;
4691        int viewFlagMasks = 0;
4692
4693        boolean setScrollContainer = false;
4694
4695        int x = 0;
4696        int y = 0;
4697
4698        float tx = 0;
4699        float ty = 0;
4700        float tz = 0;
4701        float elevation = 0;
4702        float rotation = 0;
4703        float rotationX = 0;
4704        float rotationY = 0;
4705        float sx = 1f;
4706        float sy = 1f;
4707        boolean transformSet = false;
4708
4709        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4710        int overScrollMode = mOverScrollMode;
4711        boolean initializeScrollbars = false;
4712        boolean initializeScrollIndicators = false;
4713
4714        boolean startPaddingDefined = false;
4715        boolean endPaddingDefined = false;
4716        boolean leftPaddingDefined = false;
4717        boolean rightPaddingDefined = false;
4718
4719        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4720
4721        // Set default values.
4722        viewFlagValues |= FOCUSABLE_AUTO;
4723        viewFlagMasks |= FOCUSABLE_AUTO;
4724
4725        final int N = a.getIndexCount();
4726        for (int i = 0; i < N; i++) {
4727            int attr = a.getIndex(i);
4728            switch (attr) {
4729                case com.android.internal.R.styleable.View_background:
4730                    background = a.getDrawable(attr);
4731                    break;
4732                case com.android.internal.R.styleable.View_padding:
4733                    padding = a.getDimensionPixelSize(attr, -1);
4734                    mUserPaddingLeftInitial = padding;
4735                    mUserPaddingRightInitial = padding;
4736                    leftPaddingDefined = true;
4737                    rightPaddingDefined = true;
4738                    break;
4739                case com.android.internal.R.styleable.View_paddingHorizontal:
4740                    paddingHorizontal = a.getDimensionPixelSize(attr, -1);
4741                    mUserPaddingLeftInitial = paddingHorizontal;
4742                    mUserPaddingRightInitial = paddingHorizontal;
4743                    leftPaddingDefined = true;
4744                    rightPaddingDefined = true;
4745                    break;
4746                case com.android.internal.R.styleable.View_paddingVertical:
4747                    paddingVertical = a.getDimensionPixelSize(attr, -1);
4748                    break;
4749                 case com.android.internal.R.styleable.View_paddingLeft:
4750                    leftPadding = a.getDimensionPixelSize(attr, -1);
4751                    mUserPaddingLeftInitial = leftPadding;
4752                    leftPaddingDefined = true;
4753                    break;
4754                case com.android.internal.R.styleable.View_paddingTop:
4755                    topPadding = a.getDimensionPixelSize(attr, -1);
4756                    break;
4757                case com.android.internal.R.styleable.View_paddingRight:
4758                    rightPadding = a.getDimensionPixelSize(attr, -1);
4759                    mUserPaddingRightInitial = rightPadding;
4760                    rightPaddingDefined = true;
4761                    break;
4762                case com.android.internal.R.styleable.View_paddingBottom:
4763                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4764                    break;
4765                case com.android.internal.R.styleable.View_paddingStart:
4766                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4767                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4768                    break;
4769                case com.android.internal.R.styleable.View_paddingEnd:
4770                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4771                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4772                    break;
4773                case com.android.internal.R.styleable.View_scrollX:
4774                    x = a.getDimensionPixelOffset(attr, 0);
4775                    break;
4776                case com.android.internal.R.styleable.View_scrollY:
4777                    y = a.getDimensionPixelOffset(attr, 0);
4778                    break;
4779                case com.android.internal.R.styleable.View_alpha:
4780                    setAlpha(a.getFloat(attr, 1f));
4781                    break;
4782                case com.android.internal.R.styleable.View_transformPivotX:
4783                    setPivotX(a.getDimension(attr, 0));
4784                    break;
4785                case com.android.internal.R.styleable.View_transformPivotY:
4786                    setPivotY(a.getDimension(attr, 0));
4787                    break;
4788                case com.android.internal.R.styleable.View_translationX:
4789                    tx = a.getDimension(attr, 0);
4790                    transformSet = true;
4791                    break;
4792                case com.android.internal.R.styleable.View_translationY:
4793                    ty = a.getDimension(attr, 0);
4794                    transformSet = true;
4795                    break;
4796                case com.android.internal.R.styleable.View_translationZ:
4797                    tz = a.getDimension(attr, 0);
4798                    transformSet = true;
4799                    break;
4800                case com.android.internal.R.styleable.View_elevation:
4801                    elevation = a.getDimension(attr, 0);
4802                    transformSet = true;
4803                    break;
4804                case com.android.internal.R.styleable.View_rotation:
4805                    rotation = a.getFloat(attr, 0);
4806                    transformSet = true;
4807                    break;
4808                case com.android.internal.R.styleable.View_rotationX:
4809                    rotationX = a.getFloat(attr, 0);
4810                    transformSet = true;
4811                    break;
4812                case com.android.internal.R.styleable.View_rotationY:
4813                    rotationY = a.getFloat(attr, 0);
4814                    transformSet = true;
4815                    break;
4816                case com.android.internal.R.styleable.View_scaleX:
4817                    sx = a.getFloat(attr, 1f);
4818                    transformSet = true;
4819                    break;
4820                case com.android.internal.R.styleable.View_scaleY:
4821                    sy = a.getFloat(attr, 1f);
4822                    transformSet = true;
4823                    break;
4824                case com.android.internal.R.styleable.View_id:
4825                    mID = a.getResourceId(attr, NO_ID);
4826                    break;
4827                case com.android.internal.R.styleable.View_tag:
4828                    mTag = a.getText(attr);
4829                    break;
4830                case com.android.internal.R.styleable.View_fitsSystemWindows:
4831                    if (a.getBoolean(attr, false)) {
4832                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4833                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4834                    }
4835                    break;
4836                case com.android.internal.R.styleable.View_focusable:
4837                    viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a);
4838                    if ((viewFlagValues & FOCUSABLE_AUTO) == 0) {
4839                        viewFlagMasks |= FOCUSABLE_MASK;
4840                    }
4841                    break;
4842                case com.android.internal.R.styleable.View_focusableInTouchMode:
4843                    if (a.getBoolean(attr, false)) {
4844                        // unset auto focus since focusableInTouchMode implies explicit focusable
4845                        viewFlagValues &= ~FOCUSABLE_AUTO;
4846                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4847                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4848                    }
4849                    break;
4850                case com.android.internal.R.styleable.View_clickable:
4851                    if (a.getBoolean(attr, false)) {
4852                        viewFlagValues |= CLICKABLE;
4853                        viewFlagMasks |= CLICKABLE;
4854                    }
4855                    break;
4856                case com.android.internal.R.styleable.View_longClickable:
4857                    if (a.getBoolean(attr, false)) {
4858                        viewFlagValues |= LONG_CLICKABLE;
4859                        viewFlagMasks |= LONG_CLICKABLE;
4860                    }
4861                    break;
4862                case com.android.internal.R.styleable.View_contextClickable:
4863                    if (a.getBoolean(attr, false)) {
4864                        viewFlagValues |= CONTEXT_CLICKABLE;
4865                        viewFlagMasks |= CONTEXT_CLICKABLE;
4866                    }
4867                    break;
4868                case com.android.internal.R.styleable.View_saveEnabled:
4869                    if (!a.getBoolean(attr, true)) {
4870                        viewFlagValues |= SAVE_DISABLED;
4871                        viewFlagMasks |= SAVE_DISABLED_MASK;
4872                    }
4873                    break;
4874                case com.android.internal.R.styleable.View_duplicateParentState:
4875                    if (a.getBoolean(attr, false)) {
4876                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4877                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4878                    }
4879                    break;
4880                case com.android.internal.R.styleable.View_visibility:
4881                    final int visibility = a.getInt(attr, 0);
4882                    if (visibility != 0) {
4883                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4884                        viewFlagMasks |= VISIBILITY_MASK;
4885                    }
4886                    break;
4887                case com.android.internal.R.styleable.View_layoutDirection:
4888                    // Clear any layout direction flags (included resolved bits) already set
4889                    mPrivateFlags2 &=
4890                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4891                    // Set the layout direction flags depending on the value of the attribute
4892                    final int layoutDirection = a.getInt(attr, -1);
4893                    final int value = (layoutDirection != -1) ?
4894                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4895                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4896                    break;
4897                case com.android.internal.R.styleable.View_drawingCacheQuality:
4898                    final int cacheQuality = a.getInt(attr, 0);
4899                    if (cacheQuality != 0) {
4900                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4901                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4902                    }
4903                    break;
4904                case com.android.internal.R.styleable.View_contentDescription:
4905                    setContentDescription(a.getString(attr));
4906                    break;
4907                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4908                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4909                    break;
4910                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4911                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4912                    break;
4913                case com.android.internal.R.styleable.View_labelFor:
4914                    setLabelFor(a.getResourceId(attr, NO_ID));
4915                    break;
4916                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4917                    if (!a.getBoolean(attr, true)) {
4918                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4919                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4920                    }
4921                    break;
4922                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4923                    if (!a.getBoolean(attr, true)) {
4924                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4925                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4926                    }
4927                    break;
4928                case R.styleable.View_scrollbars:
4929                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4930                    if (scrollbars != SCROLLBARS_NONE) {
4931                        viewFlagValues |= scrollbars;
4932                        viewFlagMasks |= SCROLLBARS_MASK;
4933                        initializeScrollbars = true;
4934                    }
4935                    break;
4936                //noinspection deprecation
4937                case R.styleable.View_fadingEdge:
4938                    if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
4939                        // Ignore the attribute starting with ICS
4940                        break;
4941                    }
4942                    // With builds < ICS, fall through and apply fading edges
4943                case R.styleable.View_requiresFadingEdge:
4944                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4945                    if (fadingEdge != FADING_EDGE_NONE) {
4946                        viewFlagValues |= fadingEdge;
4947                        viewFlagMasks |= FADING_EDGE_MASK;
4948                        initializeFadingEdgeInternal(a);
4949                    }
4950                    break;
4951                case R.styleable.View_scrollbarStyle:
4952                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4953                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4954                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4955                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4956                    }
4957                    break;
4958                case R.styleable.View_isScrollContainer:
4959                    setScrollContainer = true;
4960                    if (a.getBoolean(attr, false)) {
4961                        setScrollContainer(true);
4962                    }
4963                    break;
4964                case com.android.internal.R.styleable.View_keepScreenOn:
4965                    if (a.getBoolean(attr, false)) {
4966                        viewFlagValues |= KEEP_SCREEN_ON;
4967                        viewFlagMasks |= KEEP_SCREEN_ON;
4968                    }
4969                    break;
4970                case R.styleable.View_filterTouchesWhenObscured:
4971                    if (a.getBoolean(attr, false)) {
4972                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4973                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4974                    }
4975                    break;
4976                case R.styleable.View_nextFocusLeft:
4977                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4978                    break;
4979                case R.styleable.View_nextFocusRight:
4980                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4981                    break;
4982                case R.styleable.View_nextFocusUp:
4983                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4984                    break;
4985                case R.styleable.View_nextFocusDown:
4986                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4987                    break;
4988                case R.styleable.View_nextFocusForward:
4989                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4990                    break;
4991                case R.styleable.View_nextClusterForward:
4992                    mNextClusterForwardId = a.getResourceId(attr, View.NO_ID);
4993                    break;
4994                case R.styleable.View_minWidth:
4995                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4996                    break;
4997                case R.styleable.View_minHeight:
4998                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4999                    break;
5000                case R.styleable.View_onClick:
5001                    if (context.isRestricted()) {
5002                        throw new IllegalStateException("The android:onClick attribute cannot "
5003                                + "be used within a restricted context");
5004                    }
5005
5006                    final String handlerName = a.getString(attr);
5007                    if (handlerName != null) {
5008                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
5009                    }
5010                    break;
5011                case R.styleable.View_overScrollMode:
5012                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
5013                    break;
5014                case R.styleable.View_verticalScrollbarPosition:
5015                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
5016                    break;
5017                case R.styleable.View_layerType:
5018                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
5019                    break;
5020                case R.styleable.View_textDirection:
5021                    // Clear any text direction flag already set
5022                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
5023                    // Set the text direction flags depending on the value of the attribute
5024                    final int textDirection = a.getInt(attr, -1);
5025                    if (textDirection != -1) {
5026                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
5027                    }
5028                    break;
5029                case R.styleable.View_textAlignment:
5030                    // Clear any text alignment flag already set
5031                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
5032                    // Set the text alignment flag depending on the value of the attribute
5033                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
5034                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
5035                    break;
5036                case R.styleable.View_importantForAccessibility:
5037                    setImportantForAccessibility(a.getInt(attr,
5038                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
5039                    break;
5040                case R.styleable.View_accessibilityLiveRegion:
5041                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
5042                    break;
5043                case R.styleable.View_transitionName:
5044                    setTransitionName(a.getString(attr));
5045                    break;
5046                case R.styleable.View_nestedScrollingEnabled:
5047                    setNestedScrollingEnabled(a.getBoolean(attr, false));
5048                    break;
5049                case R.styleable.View_stateListAnimator:
5050                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
5051                            a.getResourceId(attr, 0)));
5052                    break;
5053                case R.styleable.View_backgroundTint:
5054                    // This will get applied later during setBackground().
5055                    if (mBackgroundTint == null) {
5056                        mBackgroundTint = new TintInfo();
5057                    }
5058                    mBackgroundTint.mTintList = a.getColorStateList(
5059                            R.styleable.View_backgroundTint);
5060                    mBackgroundTint.mHasTintList = true;
5061                    break;
5062                case R.styleable.View_backgroundTintMode:
5063                    // This will get applied later during setBackground().
5064                    if (mBackgroundTint == null) {
5065                        mBackgroundTint = new TintInfo();
5066                    }
5067                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
5068                            R.styleable.View_backgroundTintMode, -1), null);
5069                    mBackgroundTint.mHasTintMode = true;
5070                    break;
5071                case R.styleable.View_outlineProvider:
5072                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
5073                            PROVIDER_BACKGROUND));
5074                    break;
5075                case R.styleable.View_foreground:
5076                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5077                        setForeground(a.getDrawable(attr));
5078                    }
5079                    break;
5080                case R.styleable.View_foregroundGravity:
5081                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5082                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
5083                    }
5084                    break;
5085                case R.styleable.View_foregroundTintMode:
5086                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5087                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
5088                    }
5089                    break;
5090                case R.styleable.View_foregroundTint:
5091                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5092                        setForegroundTintList(a.getColorStateList(attr));
5093                    }
5094                    break;
5095                case R.styleable.View_foregroundInsidePadding:
5096                    if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) {
5097                        if (mForegroundInfo == null) {
5098                            mForegroundInfo = new ForegroundInfo();
5099                        }
5100                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
5101                                mForegroundInfo.mInsidePadding);
5102                    }
5103                    break;
5104                case R.styleable.View_scrollIndicators:
5105                    final int scrollIndicators =
5106                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
5107                                    & SCROLL_INDICATORS_PFLAG3_MASK;
5108                    if (scrollIndicators != 0) {
5109                        mPrivateFlags3 |= scrollIndicators;
5110                        initializeScrollIndicators = true;
5111                    }
5112                    break;
5113                case R.styleable.View_pointerIcon:
5114                    final int resourceId = a.getResourceId(attr, 0);
5115                    if (resourceId != 0) {
5116                        setPointerIcon(PointerIcon.load(
5117                                context.getResources(), resourceId));
5118                    } else {
5119                        final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED);
5120                        if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) {
5121                            setPointerIcon(PointerIcon.getSystemIcon(context, pointerType));
5122                        }
5123                    }
5124                    break;
5125                case R.styleable.View_forceHasOverlappingRendering:
5126                    if (a.peekValue(attr) != null) {
5127                        forceHasOverlappingRendering(a.getBoolean(attr, true));
5128                    }
5129                    break;
5130                case R.styleable.View_tooltipText:
5131                    setTooltipText(a.getText(attr));
5132                    break;
5133                case R.styleable.View_keyboardNavigationCluster:
5134                    if (a.peekValue(attr) != null) {
5135                        setKeyboardNavigationCluster(a.getBoolean(attr, true));
5136                    }
5137                    break;
5138                case R.styleable.View_focusedByDefault:
5139                    if (a.peekValue(attr) != null) {
5140                        setFocusedByDefault(a.getBoolean(attr, true));
5141                    }
5142                    break;
5143                case R.styleable.View_autofillHints:
5144                    if (a.peekValue(attr) != null) {
5145                        CharSequence[] rawHints = null;
5146                        String rawString = null;
5147
5148                        if (a.getType(attr) == TypedValue.TYPE_REFERENCE) {
5149                            int resId = a.getResourceId(attr, 0);
5150
5151                            try {
5152                                rawHints = a.getTextArray(attr);
5153                            } catch (Resources.NotFoundException e) {
5154                                rawString = getResources().getString(resId);
5155                            }
5156                        } else {
5157                            rawString = a.getString(attr);
5158                        }
5159
5160                        if (rawHints == null) {
5161                            if (rawString == null) {
5162                                throw new IllegalArgumentException(
5163                                        "Could not resolve autofillHints");
5164                            } else {
5165                                rawHints = rawString.split(",");
5166                            }
5167                        }
5168
5169                        String[] hints = new String[rawHints.length];
5170
5171                        int numHints = rawHints.length;
5172                        for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) {
5173                            hints[rawHintNum] = rawHints[rawHintNum].toString().trim();
5174                        }
5175                        setAutofillHints(hints);
5176                    }
5177                    break;
5178                case R.styleable.View_importantForAutofill:
5179                    if (a.peekValue(attr) != null) {
5180                        setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO));
5181                    }
5182                    break;
5183                case R.styleable.View_defaultFocusHighlightEnabled:
5184                    if (a.peekValue(attr) != null) {
5185                        setDefaultFocusHighlightEnabled(a.getBoolean(attr, true));
5186                    }
5187                    break;
5188            }
5189        }
5190
5191        setOverScrollMode(overScrollMode);
5192
5193        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
5194        // the resolved layout direction). Those cached values will be used later during padding
5195        // resolution.
5196        mUserPaddingStart = startPadding;
5197        mUserPaddingEnd = endPadding;
5198
5199        if (background != null) {
5200            setBackground(background);
5201        }
5202
5203        // setBackground above will record that padding is currently provided by the background.
5204        // If we have padding specified via xml, record that here instead and use it.
5205        mLeftPaddingDefined = leftPaddingDefined;
5206        mRightPaddingDefined = rightPaddingDefined;
5207
5208        if (padding >= 0) {
5209            leftPadding = padding;
5210            topPadding = padding;
5211            rightPadding = padding;
5212            bottomPadding = padding;
5213            mUserPaddingLeftInitial = padding;
5214            mUserPaddingRightInitial = padding;
5215        } else {
5216            if (paddingHorizontal >= 0) {
5217                leftPadding = paddingHorizontal;
5218                rightPadding = paddingHorizontal;
5219                mUserPaddingLeftInitial = paddingHorizontal;
5220                mUserPaddingRightInitial = paddingHorizontal;
5221            }
5222            if (paddingVertical >= 0) {
5223                topPadding = paddingVertical;
5224                bottomPadding = paddingVertical;
5225            }
5226        }
5227
5228        if (isRtlCompatibilityMode()) {
5229            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
5230            // left / right padding are used if defined (meaning here nothing to do). If they are not
5231            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
5232            // start / end and resolve them as left / right (layout direction is not taken into account).
5233            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5234            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5235            // defined.
5236            if (!mLeftPaddingDefined && startPaddingDefined) {
5237                leftPadding = startPadding;
5238            }
5239            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
5240            if (!mRightPaddingDefined && endPaddingDefined) {
5241                rightPadding = endPadding;
5242            }
5243            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
5244        } else {
5245            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
5246            // values defined. Otherwise, left /right values are used.
5247            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
5248            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
5249            // defined.
5250            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
5251
5252            if (mLeftPaddingDefined && !hasRelativePadding) {
5253                mUserPaddingLeftInitial = leftPadding;
5254            }
5255            if (mRightPaddingDefined && !hasRelativePadding) {
5256                mUserPaddingRightInitial = rightPadding;
5257            }
5258        }
5259
5260        internalSetPadding(
5261                mUserPaddingLeftInitial,
5262                topPadding >= 0 ? topPadding : mPaddingTop,
5263                mUserPaddingRightInitial,
5264                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
5265
5266        if (viewFlagMasks != 0) {
5267            setFlags(viewFlagValues, viewFlagMasks);
5268        }
5269
5270        if (initializeScrollbars) {
5271            initializeScrollbarsInternal(a);
5272        }
5273
5274        if (initializeScrollIndicators) {
5275            initializeScrollIndicatorsInternal();
5276        }
5277
5278        a.recycle();
5279
5280        // Needs to be called after mViewFlags is set
5281        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
5282            recomputePadding();
5283        }
5284
5285        if (x != 0 || y != 0) {
5286            scrollTo(x, y);
5287        }
5288
5289        if (transformSet) {
5290            setTranslationX(tx);
5291            setTranslationY(ty);
5292            setTranslationZ(tz);
5293            setElevation(elevation);
5294            setRotation(rotation);
5295            setRotationX(rotationX);
5296            setRotationY(rotationY);
5297            setScaleX(sx);
5298            setScaleY(sy);
5299        }
5300
5301        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
5302            setScrollContainer(true);
5303        }
5304
5305        computeOpaqueFlags();
5306    }
5307
5308    /**
5309     * An implementation of OnClickListener that attempts to lazily load a
5310     * named click handling method from a parent or ancestor context.
5311     */
5312    private static class DeclaredOnClickListener implements OnClickListener {
5313        private final View mHostView;
5314        private final String mMethodName;
5315
5316        private Method mResolvedMethod;
5317        private Context mResolvedContext;
5318
5319        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
5320            mHostView = hostView;
5321            mMethodName = methodName;
5322        }
5323
5324        @Override
5325        public void onClick(@NonNull View v) {
5326            if (mResolvedMethod == null) {
5327                resolveMethod(mHostView.getContext(), mMethodName);
5328            }
5329
5330            try {
5331                mResolvedMethod.invoke(mResolvedContext, v);
5332            } catch (IllegalAccessException e) {
5333                throw new IllegalStateException(
5334                        "Could not execute non-public method for android:onClick", e);
5335            } catch (InvocationTargetException e) {
5336                throw new IllegalStateException(
5337                        "Could not execute method for android:onClick", e);
5338            }
5339        }
5340
5341        @NonNull
5342        private void resolveMethod(@Nullable Context context, @NonNull String name) {
5343            while (context != null) {
5344                try {
5345                    if (!context.isRestricted()) {
5346                        final Method method = context.getClass().getMethod(mMethodName, View.class);
5347                        if (method != null) {
5348                            mResolvedMethod = method;
5349                            mResolvedContext = context;
5350                            return;
5351                        }
5352                    }
5353                } catch (NoSuchMethodException e) {
5354                    // Failed to find method, keep searching up the hierarchy.
5355                }
5356
5357                if (context instanceof ContextWrapper) {
5358                    context = ((ContextWrapper) context).getBaseContext();
5359                } else {
5360                    // Can't search up the hierarchy, null out and fail.
5361                    context = null;
5362                }
5363            }
5364
5365            final int id = mHostView.getId();
5366            final String idText = id == NO_ID ? "" : " with id '"
5367                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
5368            throw new IllegalStateException("Could not find method " + mMethodName
5369                    + "(View) in a parent or ancestor Context for android:onClick "
5370                    + "attribute defined on view " + mHostView.getClass() + idText);
5371        }
5372    }
5373
5374    /**
5375     * Non-public constructor for use in testing
5376     */
5377    View() {
5378        mResources = null;
5379        mRenderNode = RenderNode.create(getClass().getName(), this);
5380    }
5381
5382    final boolean debugDraw() {
5383        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
5384    }
5385
5386    private static SparseArray<String> getAttributeMap() {
5387        if (mAttributeMap == null) {
5388            mAttributeMap = new SparseArray<>();
5389        }
5390        return mAttributeMap;
5391    }
5392
5393    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
5394        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
5395        final int indexCount = t.getIndexCount();
5396        final String[] attributes = new String[(attrsCount + indexCount) * 2];
5397
5398        int i = 0;
5399
5400        // Store raw XML attributes.
5401        for (int j = 0; j < attrsCount; ++j) {
5402            attributes[i] = attrs.getAttributeName(j);
5403            attributes[i + 1] = attrs.getAttributeValue(j);
5404            i += 2;
5405        }
5406
5407        // Store resolved styleable attributes.
5408        final Resources res = t.getResources();
5409        final SparseArray<String> attributeMap = getAttributeMap();
5410        for (int j = 0; j < indexCount; ++j) {
5411            final int index = t.getIndex(j);
5412            if (!t.hasValueOrEmpty(index)) {
5413                // Value is undefined. Skip it.
5414                continue;
5415            }
5416
5417            final int resourceId = t.getResourceId(index, 0);
5418            if (resourceId == 0) {
5419                // Value is not a reference. Skip it.
5420                continue;
5421            }
5422
5423            String resourceName = attributeMap.get(resourceId);
5424            if (resourceName == null) {
5425                try {
5426                    resourceName = res.getResourceName(resourceId);
5427                } catch (Resources.NotFoundException e) {
5428                    resourceName = "0x" + Integer.toHexString(resourceId);
5429                }
5430                attributeMap.put(resourceId, resourceName);
5431            }
5432
5433            attributes[i] = resourceName;
5434            attributes[i + 1] = t.getString(index);
5435            i += 2;
5436        }
5437
5438        // Trim to fit contents.
5439        final String[] trimmed = new String[i];
5440        System.arraycopy(attributes, 0, trimmed, 0, i);
5441        mAttributes = trimmed;
5442    }
5443
5444    public String toString() {
5445        StringBuilder out = new StringBuilder(128);
5446        out.append(getClass().getName());
5447        out.append('{');
5448        out.append(Integer.toHexString(System.identityHashCode(this)));
5449        out.append(' ');
5450        switch (mViewFlags&VISIBILITY_MASK) {
5451            case VISIBLE: out.append('V'); break;
5452            case INVISIBLE: out.append('I'); break;
5453            case GONE: out.append('G'); break;
5454            default: out.append('.'); break;
5455        }
5456        out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.');
5457        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
5458        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
5459        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
5460        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
5461        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
5462        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
5463        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
5464        out.append(' ');
5465        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
5466        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
5467        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
5468        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
5469            out.append('p');
5470        } else {
5471            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
5472        }
5473        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
5474        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
5475        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
5476        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
5477        out.append(' ');
5478        out.append(mLeft);
5479        out.append(',');
5480        out.append(mTop);
5481        out.append('-');
5482        out.append(mRight);
5483        out.append(',');
5484        out.append(mBottom);
5485        final int id = getId();
5486        if (id != NO_ID) {
5487            out.append(" #");
5488            out.append(Integer.toHexString(id));
5489            final Resources r = mResources;
5490            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
5491                try {
5492                    String pkgname;
5493                    switch (id&0xff000000) {
5494                        case 0x7f000000:
5495                            pkgname="app";
5496                            break;
5497                        case 0x01000000:
5498                            pkgname="android";
5499                            break;
5500                        default:
5501                            pkgname = r.getResourcePackageName(id);
5502                            break;
5503                    }
5504                    String typename = r.getResourceTypeName(id);
5505                    String entryname = r.getResourceEntryName(id);
5506                    out.append(" ");
5507                    out.append(pkgname);
5508                    out.append(":");
5509                    out.append(typename);
5510                    out.append("/");
5511                    out.append(entryname);
5512                } catch (Resources.NotFoundException e) {
5513                }
5514            }
5515        }
5516        out.append("}");
5517        return out.toString();
5518    }
5519
5520    /**
5521     * <p>
5522     * Initializes the fading edges from a given set of styled attributes. This
5523     * method should be called by subclasses that need fading edges and when an
5524     * instance of these subclasses is created programmatically rather than
5525     * being inflated from XML. This method is automatically called when the XML
5526     * is inflated.
5527     * </p>
5528     *
5529     * @param a the styled attributes set to initialize the fading edges from
5530     *
5531     * @removed
5532     */
5533    protected void initializeFadingEdge(TypedArray a) {
5534        // This method probably shouldn't have been included in the SDK to begin with.
5535        // It relies on 'a' having been initialized using an attribute filter array that is
5536        // not publicly available to the SDK. The old method has been renamed
5537        // to initializeFadingEdgeInternal and hidden for framework use only;
5538        // this one initializes using defaults to make it safe to call for apps.
5539
5540        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5541
5542        initializeFadingEdgeInternal(arr);
5543
5544        arr.recycle();
5545    }
5546
5547    /**
5548     * <p>
5549     * Initializes the fading edges from a given set of styled attributes. This
5550     * method should be called by subclasses that need fading edges and when an
5551     * instance of these subclasses is created programmatically rather than
5552     * being inflated from XML. This method is automatically called when the XML
5553     * is inflated.
5554     * </p>
5555     *
5556     * @param a the styled attributes set to initialize the fading edges from
5557     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
5558     */
5559    protected void initializeFadingEdgeInternal(TypedArray a) {
5560        initScrollCache();
5561
5562        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
5563                R.styleable.View_fadingEdgeLength,
5564                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
5565    }
5566
5567    /**
5568     * Returns the size of the vertical faded edges used to indicate that more
5569     * content in this view is visible.
5570     *
5571     * @return The size in pixels of the vertical faded edge or 0 if vertical
5572     *         faded edges are not enabled for this view.
5573     * @attr ref android.R.styleable#View_fadingEdgeLength
5574     */
5575    public int getVerticalFadingEdgeLength() {
5576        if (isVerticalFadingEdgeEnabled()) {
5577            ScrollabilityCache cache = mScrollCache;
5578            if (cache != null) {
5579                return cache.fadingEdgeLength;
5580            }
5581        }
5582        return 0;
5583    }
5584
5585    /**
5586     * Set the size of the faded edge used to indicate that more content in this
5587     * view is available.  Will not change whether the fading edge is enabled; use
5588     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
5589     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
5590     * for the vertical or horizontal fading edges.
5591     *
5592     * @param length The size in pixels of the faded edge used to indicate that more
5593     *        content in this view is visible.
5594     */
5595    public void setFadingEdgeLength(int length) {
5596        initScrollCache();
5597        mScrollCache.fadingEdgeLength = length;
5598    }
5599
5600    /**
5601     * Returns the size of the horizontal faded edges used to indicate that more
5602     * content in this view is visible.
5603     *
5604     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
5605     *         faded edges are not enabled for this view.
5606     * @attr ref android.R.styleable#View_fadingEdgeLength
5607     */
5608    public int getHorizontalFadingEdgeLength() {
5609        if (isHorizontalFadingEdgeEnabled()) {
5610            ScrollabilityCache cache = mScrollCache;
5611            if (cache != null) {
5612                return cache.fadingEdgeLength;
5613            }
5614        }
5615        return 0;
5616    }
5617
5618    /**
5619     * Returns the width of the vertical scrollbar.
5620     *
5621     * @return The width in pixels of the vertical scrollbar or 0 if there
5622     *         is no vertical scrollbar.
5623     */
5624    public int getVerticalScrollbarWidth() {
5625        ScrollabilityCache cache = mScrollCache;
5626        if (cache != null) {
5627            ScrollBarDrawable scrollBar = cache.scrollBar;
5628            if (scrollBar != null) {
5629                int size = scrollBar.getSize(true);
5630                if (size <= 0) {
5631                    size = cache.scrollBarSize;
5632                }
5633                return size;
5634            }
5635            return 0;
5636        }
5637        return 0;
5638    }
5639
5640    /**
5641     * Returns the height of the horizontal scrollbar.
5642     *
5643     * @return The height in pixels of the horizontal scrollbar or 0 if
5644     *         there is no horizontal scrollbar.
5645     */
5646    protected int getHorizontalScrollbarHeight() {
5647        ScrollabilityCache cache = mScrollCache;
5648        if (cache != null) {
5649            ScrollBarDrawable scrollBar = cache.scrollBar;
5650            if (scrollBar != null) {
5651                int size = scrollBar.getSize(false);
5652                if (size <= 0) {
5653                    size = cache.scrollBarSize;
5654                }
5655                return size;
5656            }
5657            return 0;
5658        }
5659        return 0;
5660    }
5661
5662    /**
5663     * <p>
5664     * Initializes the scrollbars from a given set of styled attributes. This
5665     * method should be called by subclasses that need scrollbars and when an
5666     * instance of these subclasses is created programmatically rather than
5667     * being inflated from XML. This method is automatically called when the XML
5668     * is inflated.
5669     * </p>
5670     *
5671     * @param a the styled attributes set to initialize the scrollbars from
5672     *
5673     * @removed
5674     */
5675    protected void initializeScrollbars(TypedArray a) {
5676        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
5677        // using the View filter array which is not available to the SDK. As such, internal
5678        // framework usage now uses initializeScrollbarsInternal and we grab a default
5679        // TypedArray with the right filter instead here.
5680        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
5681
5682        initializeScrollbarsInternal(arr);
5683
5684        // We ignored the method parameter. Recycle the one we actually did use.
5685        arr.recycle();
5686    }
5687
5688    /**
5689     * <p>
5690     * Initializes the scrollbars from a given set of styled attributes. This
5691     * method should be called by subclasses that need scrollbars and when an
5692     * instance of these subclasses is created programmatically rather than
5693     * being inflated from XML. This method is automatically called when the XML
5694     * is inflated.
5695     * </p>
5696     *
5697     * @param a the styled attributes set to initialize the scrollbars from
5698     * @hide
5699     */
5700    protected void initializeScrollbarsInternal(TypedArray a) {
5701        initScrollCache();
5702
5703        final ScrollabilityCache scrollabilityCache = mScrollCache;
5704
5705        if (scrollabilityCache.scrollBar == null) {
5706            scrollabilityCache.scrollBar = new ScrollBarDrawable();
5707            scrollabilityCache.scrollBar.setState(getDrawableState());
5708            scrollabilityCache.scrollBar.setCallback(this);
5709        }
5710
5711        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
5712
5713        if (!fadeScrollbars) {
5714            scrollabilityCache.state = ScrollabilityCache.ON;
5715        }
5716        scrollabilityCache.fadeScrollBars = fadeScrollbars;
5717
5718
5719        scrollabilityCache.scrollBarFadeDuration = a.getInt(
5720                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
5721                        .getScrollBarFadeDuration());
5722        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
5723                R.styleable.View_scrollbarDefaultDelayBeforeFade,
5724                ViewConfiguration.getScrollDefaultDelay());
5725
5726
5727        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
5728                com.android.internal.R.styleable.View_scrollbarSize,
5729                ViewConfiguration.get(mContext).getScaledScrollBarSize());
5730
5731        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
5732        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
5733
5734        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
5735        if (thumb != null) {
5736            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
5737        }
5738
5739        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5740                false);
5741        if (alwaysDraw) {
5742            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5743        }
5744
5745        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5746        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5747
5748        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5749        if (thumb != null) {
5750            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5751        }
5752
5753        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5754                false);
5755        if (alwaysDraw) {
5756            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5757        }
5758
5759        // Apply layout direction to the new Drawables if needed
5760        final int layoutDirection = getLayoutDirection();
5761        if (track != null) {
5762            track.setLayoutDirection(layoutDirection);
5763        }
5764        if (thumb != null) {
5765            thumb.setLayoutDirection(layoutDirection);
5766        }
5767
5768        // Re-apply user/background padding so that scrollbar(s) get added
5769        resolvePadding();
5770    }
5771
5772    private void initializeScrollIndicatorsInternal() {
5773        // Some day maybe we'll break this into top/left/start/etc. and let the
5774        // client control it. Until then, you can have any scroll indicator you
5775        // want as long as it's a 1dp foreground-colored rectangle.
5776        if (mScrollIndicatorDrawable == null) {
5777            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5778        }
5779    }
5780
5781    /**
5782     * <p>
5783     * Initalizes the scrollability cache if necessary.
5784     * </p>
5785     */
5786    private void initScrollCache() {
5787        if (mScrollCache == null) {
5788            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5789        }
5790    }
5791
5792    private ScrollabilityCache getScrollCache() {
5793        initScrollCache();
5794        return mScrollCache;
5795    }
5796
5797    /**
5798     * Set the position of the vertical scroll bar. Should be one of
5799     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5800     * {@link #SCROLLBAR_POSITION_RIGHT}.
5801     *
5802     * @param position Where the vertical scroll bar should be positioned.
5803     */
5804    public void setVerticalScrollbarPosition(int position) {
5805        if (mVerticalScrollbarPosition != position) {
5806            mVerticalScrollbarPosition = position;
5807            computeOpaqueFlags();
5808            resolvePadding();
5809        }
5810    }
5811
5812    /**
5813     * @return The position where the vertical scroll bar will show, if applicable.
5814     * @see #setVerticalScrollbarPosition(int)
5815     */
5816    public int getVerticalScrollbarPosition() {
5817        return mVerticalScrollbarPosition;
5818    }
5819
5820    boolean isOnScrollbar(float x, float y) {
5821        if (mScrollCache == null) {
5822            return false;
5823        }
5824        x += getScrollX();
5825        y += getScrollY();
5826        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5827            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5828            getVerticalScrollBarBounds(null, touchBounds);
5829            if (touchBounds.contains((int) x, (int) y)) {
5830                return true;
5831            }
5832        }
5833        if (isHorizontalScrollBarEnabled()) {
5834            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5835            getHorizontalScrollBarBounds(null, touchBounds);
5836            if (touchBounds.contains((int) x, (int) y)) {
5837                return true;
5838            }
5839        }
5840        return false;
5841    }
5842
5843    boolean isOnScrollbarThumb(float x, float y) {
5844        return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y);
5845    }
5846
5847    private boolean isOnVerticalScrollbarThumb(float x, float y) {
5848        if (mScrollCache == null) {
5849            return false;
5850        }
5851        if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) {
5852            x += getScrollX();
5853            y += getScrollY();
5854            final Rect bounds = mScrollCache.mScrollBarBounds;
5855            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5856            getVerticalScrollBarBounds(bounds, touchBounds);
5857            final int range = computeVerticalScrollRange();
5858            final int offset = computeVerticalScrollOffset();
5859            final int extent = computeVerticalScrollExtent();
5860            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(),
5861                    extent, range);
5862            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength,
5863                    extent, range, offset);
5864            final int thumbTop = bounds.top + thumbOffset;
5865            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5866            if (x >= touchBounds.left && x <= touchBounds.right
5867                    && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) {
5868                return true;
5869            }
5870        }
5871        return false;
5872    }
5873
5874    private boolean isOnHorizontalScrollbarThumb(float x, float y) {
5875        if (mScrollCache == null) {
5876            return false;
5877        }
5878        if (isHorizontalScrollBarEnabled()) {
5879            x += getScrollX();
5880            y += getScrollY();
5881            final Rect bounds = mScrollCache.mScrollBarBounds;
5882            final Rect touchBounds = mScrollCache.mScrollBarTouchBounds;
5883            getHorizontalScrollBarBounds(bounds, touchBounds);
5884            final int range = computeHorizontalScrollRange();
5885            final int offset = computeHorizontalScrollOffset();
5886            final int extent = computeHorizontalScrollExtent();
5887            final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(),
5888                    extent, range);
5889            final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength,
5890                    extent, range, offset);
5891            final int thumbLeft = bounds.left + thumbOffset;
5892            final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2;
5893            if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust
5894                    && y >= touchBounds.top && y <= touchBounds.bottom) {
5895                return true;
5896            }
5897        }
5898        return false;
5899    }
5900
5901    boolean isDraggingScrollBar() {
5902        return mScrollCache != null
5903                && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING;
5904    }
5905
5906    /**
5907     * Sets the state of all scroll indicators.
5908     * <p>
5909     * See {@link #setScrollIndicators(int, int)} for usage information.
5910     *
5911     * @param indicators a bitmask of indicators that should be enabled, or
5912     *                   {@code 0} to disable all indicators
5913     * @see #setScrollIndicators(int, int)
5914     * @see #getScrollIndicators()
5915     * @attr ref android.R.styleable#View_scrollIndicators
5916     */
5917    public void setScrollIndicators(@ScrollIndicators int indicators) {
5918        setScrollIndicators(indicators,
5919                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5920    }
5921
5922    /**
5923     * Sets the state of the scroll indicators specified by the mask. To change
5924     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5925     * <p>
5926     * When a scroll indicator is enabled, it will be displayed if the view
5927     * can scroll in the direction of the indicator.
5928     * <p>
5929     * Multiple indicator types may be enabled or disabled by passing the
5930     * logical OR of the desired types. If multiple types are specified, they
5931     * will all be set to the same enabled state.
5932     * <p>
5933     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5934     *
5935     * @param indicators the indicator direction, or the logical OR of multiple
5936     *             indicator directions. One or more of:
5937     *             <ul>
5938     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5939     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5940     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5941     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5942     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5943     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5944     *             </ul>
5945     * @see #setScrollIndicators(int)
5946     * @see #getScrollIndicators()
5947     * @attr ref android.R.styleable#View_scrollIndicators
5948     */
5949    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5950        // Shift and sanitize mask.
5951        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5952        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5953
5954        // Shift and mask indicators.
5955        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5956        indicators &= mask;
5957
5958        // Merge with non-masked flags.
5959        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5960
5961        if (mPrivateFlags3 != updatedFlags) {
5962            mPrivateFlags3 = updatedFlags;
5963
5964            if (indicators != 0) {
5965                initializeScrollIndicatorsInternal();
5966            }
5967            invalidate();
5968        }
5969    }
5970
5971    /**
5972     * Returns a bitmask representing the enabled scroll indicators.
5973     * <p>
5974     * For example, if the top and left scroll indicators are enabled and all
5975     * other indicators are disabled, the return value will be
5976     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5977     * <p>
5978     * To check whether the bottom scroll indicator is enabled, use the value
5979     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5980     *
5981     * @return a bitmask representing the enabled scroll indicators
5982     */
5983    @ScrollIndicators
5984    public int getScrollIndicators() {
5985        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5986                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5987    }
5988
5989    ListenerInfo getListenerInfo() {
5990        if (mListenerInfo != null) {
5991            return mListenerInfo;
5992        }
5993        mListenerInfo = new ListenerInfo();
5994        return mListenerInfo;
5995    }
5996
5997    /**
5998     * Register a callback to be invoked when the scroll X or Y positions of
5999     * this view change.
6000     * <p>
6001     * <b>Note:</b> Some views handle scrolling independently from View and may
6002     * have their own separate listeners for scroll-type events. For example,
6003     * {@link android.widget.ListView ListView} allows clients to register an
6004     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
6005     * to listen for changes in list scroll position.
6006     *
6007     * @param l The listener to notify when the scroll X or Y position changes.
6008     * @see android.view.View#getScrollX()
6009     * @see android.view.View#getScrollY()
6010     */
6011    public void setOnScrollChangeListener(OnScrollChangeListener l) {
6012        getListenerInfo().mOnScrollChangeListener = l;
6013    }
6014
6015    /**
6016     * Register a callback to be invoked when focus of this view changed.
6017     *
6018     * @param l The callback that will run.
6019     */
6020    public void setOnFocusChangeListener(OnFocusChangeListener l) {
6021        getListenerInfo().mOnFocusChangeListener = l;
6022    }
6023
6024    /**
6025     * Add a listener that will be called when the bounds of the view change due to
6026     * layout processing.
6027     *
6028     * @param listener The listener that will be called when layout bounds change.
6029     */
6030    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
6031        ListenerInfo li = getListenerInfo();
6032        if (li.mOnLayoutChangeListeners == null) {
6033            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
6034        }
6035        if (!li.mOnLayoutChangeListeners.contains(listener)) {
6036            li.mOnLayoutChangeListeners.add(listener);
6037        }
6038    }
6039
6040    /**
6041     * Remove a listener for layout changes.
6042     *
6043     * @param listener The listener for layout bounds change.
6044     */
6045    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
6046        ListenerInfo li = mListenerInfo;
6047        if (li == null || li.mOnLayoutChangeListeners == null) {
6048            return;
6049        }
6050        li.mOnLayoutChangeListeners.remove(listener);
6051    }
6052
6053    /**
6054     * Add a listener for attach state changes.
6055     *
6056     * This listener will be called whenever this view is attached or detached
6057     * from a window. Remove the listener using
6058     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
6059     *
6060     * @param listener Listener to attach
6061     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
6062     */
6063    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6064        ListenerInfo li = getListenerInfo();
6065        if (li.mOnAttachStateChangeListeners == null) {
6066            li.mOnAttachStateChangeListeners
6067                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
6068        }
6069        li.mOnAttachStateChangeListeners.add(listener);
6070    }
6071
6072    /**
6073     * Remove a listener for attach state changes. The listener will receive no further
6074     * notification of window attach/detach events.
6075     *
6076     * @param listener Listener to remove
6077     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
6078     */
6079    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
6080        ListenerInfo li = mListenerInfo;
6081        if (li == null || li.mOnAttachStateChangeListeners == null) {
6082            return;
6083        }
6084        li.mOnAttachStateChangeListeners.remove(listener);
6085    }
6086
6087    /**
6088     * Returns the focus-change callback registered for this view.
6089     *
6090     * @return The callback, or null if one is not registered.
6091     */
6092    public OnFocusChangeListener getOnFocusChangeListener() {
6093        ListenerInfo li = mListenerInfo;
6094        return li != null ? li.mOnFocusChangeListener : null;
6095    }
6096
6097    /**
6098     * Register a callback to be invoked when this view is clicked. If this view is not
6099     * clickable, it becomes clickable.
6100     *
6101     * @param l The callback that will run
6102     *
6103     * @see #setClickable(boolean)
6104     */
6105    public void setOnClickListener(@Nullable OnClickListener l) {
6106        if (!isClickable()) {
6107            setClickable(true);
6108        }
6109        getListenerInfo().mOnClickListener = l;
6110    }
6111
6112    /**
6113     * Return whether this view has an attached OnClickListener.  Returns
6114     * true if there is a listener, false if there is none.
6115     */
6116    public boolean hasOnClickListeners() {
6117        ListenerInfo li = mListenerInfo;
6118        return (li != null && li.mOnClickListener != null);
6119    }
6120
6121    /**
6122     * Register a callback to be invoked when this view is clicked and held. If this view is not
6123     * long clickable, it becomes long clickable.
6124     *
6125     * @param l The callback that will run
6126     *
6127     * @see #setLongClickable(boolean)
6128     */
6129    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
6130        if (!isLongClickable()) {
6131            setLongClickable(true);
6132        }
6133        getListenerInfo().mOnLongClickListener = l;
6134    }
6135
6136    /**
6137     * Register a callback to be invoked when this view is context clicked. If the view is not
6138     * context clickable, it becomes context clickable.
6139     *
6140     * @param l The callback that will run
6141     * @see #setContextClickable(boolean)
6142     */
6143    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
6144        if (!isContextClickable()) {
6145            setContextClickable(true);
6146        }
6147        getListenerInfo().mOnContextClickListener = l;
6148    }
6149
6150    /**
6151     * Register a callback to be invoked when the context menu for this view is
6152     * being built. If this view is not long clickable, it becomes long clickable.
6153     *
6154     * @param l The callback that will run
6155     *
6156     */
6157    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
6158        if (!isLongClickable()) {
6159            setLongClickable(true);
6160        }
6161        getListenerInfo().mOnCreateContextMenuListener = l;
6162    }
6163
6164    /**
6165     * Set an observer to collect stats for each frame rendered for this view.
6166     *
6167     * @hide
6168     */
6169    public void addFrameMetricsListener(Window window,
6170            Window.OnFrameMetricsAvailableListener listener,
6171            Handler handler) {
6172        if (mAttachInfo != null) {
6173            if (mAttachInfo.mThreadedRenderer != null) {
6174                if (mFrameMetricsObservers == null) {
6175                    mFrameMetricsObservers = new ArrayList<>();
6176                }
6177
6178                FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6179                        handler.getLooper(), listener);
6180                mFrameMetricsObservers.add(fmo);
6181                mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo);
6182            } else {
6183                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6184            }
6185        } else {
6186            if (mFrameMetricsObservers == null) {
6187                mFrameMetricsObservers = new ArrayList<>();
6188            }
6189
6190            FrameMetricsObserver fmo = new FrameMetricsObserver(window,
6191                    handler.getLooper(), listener);
6192            mFrameMetricsObservers.add(fmo);
6193        }
6194    }
6195
6196    /**
6197     * Remove observer configured to collect frame stats for this view.
6198     *
6199     * @hide
6200     */
6201    public void removeFrameMetricsListener(
6202            Window.OnFrameMetricsAvailableListener listener) {
6203        ThreadedRenderer renderer = getThreadedRenderer();
6204        FrameMetricsObserver fmo = findFrameMetricsObserver(listener);
6205        if (fmo == null) {
6206            throw new IllegalArgumentException(
6207                    "attempt to remove OnFrameMetricsAvailableListener that was never added");
6208        }
6209
6210        if (mFrameMetricsObservers != null) {
6211            mFrameMetricsObservers.remove(fmo);
6212            if (renderer != null) {
6213                renderer.removeFrameMetricsObserver(fmo);
6214            }
6215        }
6216    }
6217
6218    private void registerPendingFrameMetricsObservers() {
6219        if (mFrameMetricsObservers != null) {
6220            ThreadedRenderer renderer = getThreadedRenderer();
6221            if (renderer != null) {
6222                for (FrameMetricsObserver fmo : mFrameMetricsObservers) {
6223                    renderer.addFrameMetricsObserver(fmo);
6224                }
6225            } else {
6226                Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats");
6227            }
6228        }
6229    }
6230
6231    private FrameMetricsObserver findFrameMetricsObserver(
6232            Window.OnFrameMetricsAvailableListener listener) {
6233        for (int i = 0; i < mFrameMetricsObservers.size(); i++) {
6234            FrameMetricsObserver observer = mFrameMetricsObservers.get(i);
6235            if (observer.mListener == listener) {
6236                return observer;
6237            }
6238        }
6239
6240        return null;
6241    }
6242
6243    /**
6244     * Call this view's OnClickListener, if it is defined.  Performs all normal
6245     * actions associated with clicking: reporting accessibility event, playing
6246     * a sound, etc.
6247     *
6248     * @return True there was an assigned OnClickListener that was called, false
6249     *         otherwise is returned.
6250     */
6251    public boolean performClick() {
6252        final boolean result;
6253        final ListenerInfo li = mListenerInfo;
6254        if (li != null && li.mOnClickListener != null) {
6255            playSoundEffect(SoundEffectConstants.CLICK);
6256            li.mOnClickListener.onClick(this);
6257            result = true;
6258        } else {
6259            result = false;
6260        }
6261
6262        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
6263
6264        notifyEnterOrExitForAutoFillIfNeeded(true);
6265
6266        return result;
6267    }
6268
6269    /**
6270     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
6271     * this only calls the listener, and does not do any associated clicking
6272     * actions like reporting an accessibility event.
6273     *
6274     * @return True there was an assigned OnClickListener that was called, false
6275     *         otherwise is returned.
6276     */
6277    public boolean callOnClick() {
6278        ListenerInfo li = mListenerInfo;
6279        if (li != null && li.mOnClickListener != null) {
6280            li.mOnClickListener.onClick(this);
6281            return true;
6282        }
6283        return false;
6284    }
6285
6286    /**
6287     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6288     * context menu if the OnLongClickListener did not consume the event.
6289     *
6290     * @return {@code true} if one of the above receivers consumed the event,
6291     *         {@code false} otherwise
6292     */
6293    public boolean performLongClick() {
6294        return performLongClickInternal(mLongClickX, mLongClickY);
6295    }
6296
6297    /**
6298     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6299     * context menu if the OnLongClickListener did not consume the event,
6300     * anchoring it to an (x,y) coordinate.
6301     *
6302     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6303     *          to disable anchoring
6304     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6305     *          to disable anchoring
6306     * @return {@code true} if one of the above receivers consumed the event,
6307     *         {@code false} otherwise
6308     */
6309    public boolean performLongClick(float x, float y) {
6310        mLongClickX = x;
6311        mLongClickY = y;
6312        final boolean handled = performLongClick();
6313        mLongClickX = Float.NaN;
6314        mLongClickY = Float.NaN;
6315        return handled;
6316    }
6317
6318    /**
6319     * Calls this view's OnLongClickListener, if it is defined. Invokes the
6320     * context menu if the OnLongClickListener did not consume the event,
6321     * optionally anchoring it to an (x,y) coordinate.
6322     *
6323     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
6324     *          to disable anchoring
6325     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
6326     *          to disable anchoring
6327     * @return {@code true} if one of the above receivers consumed the event,
6328     *         {@code false} otherwise
6329     */
6330    private boolean performLongClickInternal(float x, float y) {
6331        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
6332
6333        boolean handled = false;
6334        final ListenerInfo li = mListenerInfo;
6335        if (li != null && li.mOnLongClickListener != null) {
6336            handled = li.mOnLongClickListener.onLongClick(View.this);
6337        }
6338        if (!handled) {
6339            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
6340            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
6341        }
6342        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
6343            if (!handled) {
6344                handled = showLongClickTooltip((int) x, (int) y);
6345            }
6346        }
6347        if (handled) {
6348            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
6349        }
6350        return handled;
6351    }
6352
6353    /**
6354     * Call this view's OnContextClickListener, if it is defined.
6355     *
6356     * @param x the x coordinate of the context click
6357     * @param y the y coordinate of the context click
6358     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6359     *         otherwise.
6360     */
6361    public boolean performContextClick(float x, float y) {
6362        return performContextClick();
6363    }
6364
6365    /**
6366     * Call this view's OnContextClickListener, if it is defined.
6367     *
6368     * @return True if there was an assigned OnContextClickListener that consumed the event, false
6369     *         otherwise.
6370     */
6371    public boolean performContextClick() {
6372        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
6373
6374        boolean handled = false;
6375        ListenerInfo li = mListenerInfo;
6376        if (li != null && li.mOnContextClickListener != null) {
6377            handled = li.mOnContextClickListener.onContextClick(View.this);
6378        }
6379        if (handled) {
6380            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
6381        }
6382        return handled;
6383    }
6384
6385    /**
6386     * Performs button-related actions during a touch down event.
6387     *
6388     * @param event The event.
6389     * @return True if the down was consumed.
6390     *
6391     * @hide
6392     */
6393    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
6394        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
6395            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
6396            showContextMenu(event.getX(), event.getY());
6397            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6398            return true;
6399        }
6400        return false;
6401    }
6402
6403    /**
6404     * Shows the context menu for this view.
6405     *
6406     * @return {@code true} if the context menu was shown, {@code false}
6407     *         otherwise
6408     * @see #showContextMenu(float, float)
6409     */
6410    public boolean showContextMenu() {
6411        return getParent().showContextMenuForChild(this);
6412    }
6413
6414    /**
6415     * Shows the context menu for this view anchored to the specified
6416     * view-relative coordinate.
6417     *
6418     * @param x the X coordinate in pixels relative to the view to which the
6419     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6420     * @param y the Y coordinate in pixels relative to the view to which the
6421     *          menu should be anchored, or {@link Float#NaN} to disable anchoring
6422     * @return {@code true} if the context menu was shown, {@code false}
6423     *         otherwise
6424     */
6425    public boolean showContextMenu(float x, float y) {
6426        return getParent().showContextMenuForChild(this, x, y);
6427    }
6428
6429    /**
6430     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
6431     *
6432     * @param callback Callback that will control the lifecycle of the action mode
6433     * @return The new action mode if it is started, null otherwise
6434     *
6435     * @see ActionMode
6436     * @see #startActionMode(android.view.ActionMode.Callback, int)
6437     */
6438    public ActionMode startActionMode(ActionMode.Callback callback) {
6439        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
6440    }
6441
6442    /**
6443     * Start an action mode with the given type.
6444     *
6445     * @param callback Callback that will control the lifecycle of the action mode
6446     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
6447     * @return The new action mode if it is started, null otherwise
6448     *
6449     * @see ActionMode
6450     */
6451    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
6452        ViewParent parent = getParent();
6453        if (parent == null) return null;
6454        try {
6455            return parent.startActionModeForChild(this, callback, type);
6456        } catch (AbstractMethodError ame) {
6457            // Older implementations of custom views might not implement this.
6458            return parent.startActionModeForChild(this, callback);
6459        }
6460    }
6461
6462    /**
6463     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
6464     * Context, creating a unique View identifier to retrieve the result.
6465     *
6466     * @param intent The Intent to be started.
6467     * @param requestCode The request code to use.
6468     * @hide
6469     */
6470    public void startActivityForResult(Intent intent, int requestCode) {
6471        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
6472        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
6473    }
6474
6475    /**
6476     * If this View corresponds to the calling who, dispatches the activity result.
6477     * @param who The identifier for the targeted View to receive the result.
6478     * @param requestCode The integer request code originally supplied to
6479     *                    startActivityForResult(), allowing you to identify who this
6480     *                    result came from.
6481     * @param resultCode The integer result code returned by the child activity
6482     *                   through its setResult().
6483     * @param data An Intent, which can return result data to the caller
6484     *               (various data can be attached to Intent "extras").
6485     * @return {@code true} if the activity result was dispatched.
6486     * @hide
6487     */
6488    public boolean dispatchActivityResult(
6489            String who, int requestCode, int resultCode, Intent data) {
6490        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
6491            onActivityResult(requestCode, resultCode, data);
6492            mStartActivityRequestWho = null;
6493            return true;
6494        }
6495        return false;
6496    }
6497
6498    /**
6499     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
6500     *
6501     * @param requestCode The integer request code originally supplied to
6502     *                    startActivityForResult(), allowing you to identify who this
6503     *                    result came from.
6504     * @param resultCode The integer result code returned by the child activity
6505     *                   through its setResult().
6506     * @param data An Intent, which can return result data to the caller
6507     *               (various data can be attached to Intent "extras").
6508     * @hide
6509     */
6510    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6511        // Do nothing.
6512    }
6513
6514    /**
6515     * Register a callback to be invoked when a hardware key is pressed in this view.
6516     * Key presses in software input methods will generally not trigger the methods of
6517     * this listener.
6518     * @param l the key listener to attach to this view
6519     */
6520    public void setOnKeyListener(OnKeyListener l) {
6521        getListenerInfo().mOnKeyListener = l;
6522    }
6523
6524    /**
6525     * Register a callback to be invoked when a touch event is sent to this view.
6526     * @param l the touch listener to attach to this view
6527     */
6528    public void setOnTouchListener(OnTouchListener l) {
6529        getListenerInfo().mOnTouchListener = l;
6530    }
6531
6532    /**
6533     * Register a callback to be invoked when a generic motion event is sent to this view.
6534     * @param l the generic motion listener to attach to this view
6535     */
6536    public void setOnGenericMotionListener(OnGenericMotionListener l) {
6537        getListenerInfo().mOnGenericMotionListener = l;
6538    }
6539
6540    /**
6541     * Register a callback to be invoked when a hover event is sent to this view.
6542     * @param l the hover listener to attach to this view
6543     */
6544    public void setOnHoverListener(OnHoverListener l) {
6545        getListenerInfo().mOnHoverListener = l;
6546    }
6547
6548    /**
6549     * Register a drag event listener callback object for this View. The parameter is
6550     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
6551     * View, the system calls the
6552     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
6553     * @param l An implementation of {@link android.view.View.OnDragListener}.
6554     */
6555    public void setOnDragListener(OnDragListener l) {
6556        getListenerInfo().mOnDragListener = l;
6557    }
6558
6559    /**
6560     * Give this view focus. This will cause
6561     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
6562     *
6563     * Note: this does not check whether this {@link View} should get focus, it just
6564     * gives it focus no matter what.  It should only be called internally by framework
6565     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
6566     *
6567     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
6568     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
6569     *        focus moved when requestFocus() is called. It may not always
6570     *        apply, in which case use the default View.FOCUS_DOWN.
6571     * @param previouslyFocusedRect The rectangle of the view that had focus
6572     *        prior in this View's coordinate system.
6573     */
6574    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
6575        if (DBG) {
6576            System.out.println(this + " requestFocus()");
6577        }
6578
6579        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
6580            mPrivateFlags |= PFLAG_FOCUSED;
6581
6582            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
6583
6584            if (mParent != null) {
6585                mParent.requestChildFocus(this, this);
6586                updateFocusedInCluster(oldFocus, direction);
6587            }
6588
6589            if (mAttachInfo != null) {
6590                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
6591            }
6592
6593            onFocusChanged(true, direction, previouslyFocusedRect);
6594            refreshDrawableState();
6595        }
6596    }
6597
6598    /**
6599     * Sets this view's preference for reveal behavior when it gains focus.
6600     *
6601     * <p>When set to true, this is a signal to ancestor views in the hierarchy that
6602     * this view would prefer to be brought fully into view when it gains focus.
6603     * For example, a text field that a user is meant to type into. Other views such
6604     * as scrolling containers may prefer to opt-out of this behavior.</p>
6605     *
6606     * <p>The default value for views is true, though subclasses may change this
6607     * based on their preferred behavior.</p>
6608     *
6609     * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise
6610     *
6611     * @see #getRevealOnFocusHint()
6612     */
6613    public final void setRevealOnFocusHint(boolean revealOnFocus) {
6614        if (revealOnFocus) {
6615            mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS;
6616        } else {
6617            mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS;
6618        }
6619    }
6620
6621    /**
6622     * Returns this view's preference for reveal behavior when it gains focus.
6623     *
6624     * <p>When this method returns true for a child view requesting focus, ancestor
6625     * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)}
6626     * should make a best effort to make the newly focused child fully visible to the user.
6627     * When it returns false, ancestor views should preferably not disrupt scroll positioning or
6628     * other properties affecting visibility to the user as part of the focus change.</p>
6629     *
6630     * @return true if this view would prefer to become fully visible when it gains focus,
6631     *         false if it would prefer not to disrupt scroll positioning
6632     *
6633     * @see #setRevealOnFocusHint(boolean)
6634     */
6635    public final boolean getRevealOnFocusHint() {
6636        return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0;
6637    }
6638
6639    /**
6640     * Populates <code>outRect</code> with the hotspot bounds. By default,
6641     * the hotspot bounds are identical to the screen bounds.
6642     *
6643     * @param outRect rect to populate with hotspot bounds
6644     * @hide Only for internal use by views and widgets.
6645     */
6646    public void getHotspotBounds(Rect outRect) {
6647        final Drawable background = getBackground();
6648        if (background != null) {
6649            background.getHotspotBounds(outRect);
6650        } else {
6651            getBoundsOnScreen(outRect);
6652        }
6653    }
6654
6655    /**
6656     * Request that a rectangle of this view be visible on the screen,
6657     * scrolling if necessary just enough.
6658     *
6659     * <p>A View should call this if it maintains some notion of which part
6660     * of its content is interesting.  For example, a text editing view
6661     * should call this when its cursor moves.
6662     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6663     * It should not be affected by which part of the View is currently visible or its scroll
6664     * position.
6665     *
6666     * @param rectangle The rectangle in the View's content coordinate space
6667     * @return Whether any parent scrolled.
6668     */
6669    public boolean requestRectangleOnScreen(Rect rectangle) {
6670        return requestRectangleOnScreen(rectangle, false);
6671    }
6672
6673    /**
6674     * Request that a rectangle of this view be visible on the screen,
6675     * scrolling if necessary just enough.
6676     *
6677     * <p>A View should call this if it maintains some notion of which part
6678     * of its content is interesting.  For example, a text editing view
6679     * should call this when its cursor moves.
6680     * <p>The Rectangle passed into this method should be in the View's content coordinate space.
6681     * It should not be affected by which part of the View is currently visible or its scroll
6682     * position.
6683     * <p>When <code>immediate</code> is set to true, scrolling will not be
6684     * animated.
6685     *
6686     * @param rectangle The rectangle in the View's content coordinate space
6687     * @param immediate True to forbid animated scrolling, false otherwise
6688     * @return Whether any parent scrolled.
6689     */
6690    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
6691        if (mParent == null) {
6692            return false;
6693        }
6694
6695        View child = this;
6696
6697        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
6698        position.set(rectangle);
6699
6700        ViewParent parent = mParent;
6701        boolean scrolled = false;
6702        while (parent != null) {
6703            rectangle.set((int) position.left, (int) position.top,
6704                    (int) position.right, (int) position.bottom);
6705
6706            scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate);
6707
6708            if (!(parent instanceof View)) {
6709                break;
6710            }
6711
6712            // move it from child's content coordinate space to parent's content coordinate space
6713            position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY());
6714
6715            child = (View) parent;
6716            parent = child.getParent();
6717        }
6718
6719        return scrolled;
6720    }
6721
6722    /**
6723     * Called when this view wants to give up focus. If focus is cleared
6724     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
6725     * <p>
6726     * <strong>Note:</strong> When a View clears focus the framework is trying
6727     * to give focus to the first focusable View from the top. Hence, if this
6728     * View is the first from the top that can take focus, then all callbacks
6729     * related to clearing focus will be invoked after which the framework will
6730     * give focus to this view.
6731     * </p>
6732     */
6733    public void clearFocus() {
6734        if (DBG) {
6735            System.out.println(this + " clearFocus()");
6736        }
6737
6738        clearFocusInternal(null, true, true);
6739    }
6740
6741    /**
6742     * Clears focus from the view, optionally propagating the change up through
6743     * the parent hierarchy and requesting that the root view place new focus.
6744     *
6745     * @param propagate whether to propagate the change up through the parent
6746     *            hierarchy
6747     * @param refocus when propagate is true, specifies whether to request the
6748     *            root view place new focus
6749     */
6750    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
6751        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
6752            mPrivateFlags &= ~PFLAG_FOCUSED;
6753
6754            if (propagate && mParent != null) {
6755                mParent.clearChildFocus(this);
6756            }
6757
6758            onFocusChanged(false, 0, null);
6759            refreshDrawableState();
6760
6761            if (propagate && (!refocus || !rootViewRequestFocus())) {
6762                notifyGlobalFocusCleared(this);
6763            }
6764        }
6765    }
6766
6767    void notifyGlobalFocusCleared(View oldFocus) {
6768        if (oldFocus != null && mAttachInfo != null) {
6769            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
6770        }
6771    }
6772
6773    boolean rootViewRequestFocus() {
6774        final View root = getRootView();
6775        return root != null && root.requestFocus();
6776    }
6777
6778    /**
6779     * Called internally by the view system when a new view is getting focus.
6780     * This is what clears the old focus.
6781     * <p>
6782     * <b>NOTE:</b> The parent view's focused child must be updated manually
6783     * after calling this method. Otherwise, the view hierarchy may be left in
6784     * an inconstent state.
6785     */
6786    void unFocus(View focused) {
6787        if (DBG) {
6788            System.out.println(this + " unFocus()");
6789        }
6790
6791        clearFocusInternal(focused, false, false);
6792    }
6793
6794    /**
6795     * Returns true if this view has focus itself, or is the ancestor of the
6796     * view that has focus.
6797     *
6798     * @return True if this view has or contains focus, false otherwise.
6799     */
6800    @ViewDebug.ExportedProperty(category = "focus")
6801    public boolean hasFocus() {
6802        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6803    }
6804
6805    /**
6806     * Returns true if this view is focusable or if it contains a reachable View
6807     * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()"
6808     * is a view whose parents do not block descendants focus.
6809     * Only {@link #VISIBLE} views are considered focusable.
6810     *
6811     * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable
6812     * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}.
6813     * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of
6814     * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return
6815     * {@code false} for views not explicitly marked as focusable.
6816     * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O}
6817     * behavior.</p>
6818     *
6819     * @return {@code true} if the view is focusable or if the view contains a focusable
6820     *         view, {@code false} otherwise
6821     *
6822     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
6823     * @see ViewGroup#getTouchscreenBlocksFocus()
6824     * @see #hasExplicitFocusable()
6825     */
6826    public boolean hasFocusable() {
6827        return hasFocusable(!sHasFocusableExcludeAutoFocusable, false);
6828    }
6829
6830    /**
6831     * Returns true if this view is focusable or if it contains a reachable View
6832     * for which {@link #hasExplicitFocusable()} returns {@code true}.
6833     * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus.
6834     * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return
6835     * {@link #FOCUSABLE} are considered focusable.
6836     *
6837     * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of
6838     * {@link #hasFocusable()} in that only views explicitly set focusable will cause
6839     * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves
6840     * to focusable will not.</p>
6841     *
6842     * @return {@code true} if the view is focusable or if the view contains a focusable
6843     *         view, {@code false} otherwise
6844     *
6845     * @see #hasFocusable()
6846     */
6847    public boolean hasExplicitFocusable() {
6848        return hasFocusable(false, true);
6849    }
6850
6851    boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) {
6852        if (!isFocusableInTouchMode()) {
6853            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
6854                final ViewGroup g = (ViewGroup) p;
6855                if (g.shouldBlockFocusForTouchscreen()) {
6856                    return false;
6857                }
6858            }
6859        }
6860
6861        // Invisible and gone views are never focusable.
6862        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6863            return false;
6864        }
6865
6866        // Only use effective focusable value when allowed.
6867        if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) {
6868            return true;
6869        }
6870
6871        return false;
6872    }
6873
6874    /**
6875     * Called by the view system when the focus state of this view changes.
6876     * When the focus change event is caused by directional navigation, direction
6877     * and previouslyFocusedRect provide insight into where the focus is coming from.
6878     * When overriding, be sure to call up through to the super class so that
6879     * the standard focus handling will occur.
6880     *
6881     * @param gainFocus True if the View has focus; false otherwise.
6882     * @param direction The direction focus has moved when requestFocus()
6883     *                  is called to give this view focus. Values are
6884     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
6885     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
6886     *                  It may not always apply, in which case use the default.
6887     * @param previouslyFocusedRect The rectangle, in this view's coordinate
6888     *        system, of the previously focused view.  If applicable, this will be
6889     *        passed in as finer grained information about where the focus is coming
6890     *        from (in addition to direction).  Will be <code>null</code> otherwise.
6891     */
6892    @CallSuper
6893    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
6894            @Nullable Rect previouslyFocusedRect) {
6895        if (gainFocus) {
6896            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6897        } else {
6898            notifyViewAccessibilityStateChangedIfNeeded(
6899                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6900        }
6901
6902        // Here we check whether we still need the default focus highlight, and switch it on/off.
6903        switchDefaultFocusHighlight();
6904
6905        InputMethodManager imm = InputMethodManager.peekInstance();
6906        if (!gainFocus) {
6907            if (isPressed()) {
6908                setPressed(false);
6909            }
6910            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6911                imm.focusOut(this);
6912            }
6913            onFocusLost();
6914        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
6915            imm.focusIn(this);
6916        }
6917
6918        invalidate(true);
6919        ListenerInfo li = mListenerInfo;
6920        if (li != null && li.mOnFocusChangeListener != null) {
6921            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
6922        }
6923
6924        if (mAttachInfo != null) {
6925            mAttachInfo.mKeyDispatchState.reset(this);
6926        }
6927
6928        notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
6929    }
6930
6931    private void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {
6932        if (isAutofillable() && isAttachedToWindow()) {
6933            AutofillManager afm = getAutofillManager();
6934            if (afm != null) {
6935                if (enter && hasWindowFocus() && isFocused()) {
6936                    // We have not been laid out yet, hence cannot evaluate
6937                    // whether this view is visible to the user, we will do
6938                    // the evaluation once layout is complete.
6939                    if (!isLaidOut()) {
6940                        mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
6941                    } else if (isVisibleToUser()) {
6942                        afm.notifyViewEntered(this);
6943                    }
6944                } else if (!hasWindowFocus() || !isFocused()) {
6945                    afm.notifyViewExited(this);
6946                }
6947            }
6948        }
6949    }
6950
6951    /**
6952     * Sends an accessibility event of the given type. If accessibility is
6953     * not enabled this method has no effect. The default implementation calls
6954     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
6955     * to populate information about the event source (this View), then calls
6956     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
6957     * populate the text content of the event source including its descendants,
6958     * and last calls
6959     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
6960     * on its parent to request sending of the event to interested parties.
6961     * <p>
6962     * If an {@link AccessibilityDelegate} has been specified via calling
6963     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6964     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
6965     * responsible for handling this call.
6966     * </p>
6967     *
6968     * @param eventType The type of the event to send, as defined by several types from
6969     * {@link android.view.accessibility.AccessibilityEvent}, such as
6970     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
6971     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
6972     *
6973     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6974     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6975     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
6976     * @see AccessibilityDelegate
6977     */
6978    public void sendAccessibilityEvent(int eventType) {
6979        if (mAccessibilityDelegate != null) {
6980            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
6981        } else {
6982            sendAccessibilityEventInternal(eventType);
6983        }
6984    }
6985
6986    /**
6987     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
6988     * {@link AccessibilityEvent} to make an announcement which is related to some
6989     * sort of a context change for which none of the events representing UI transitions
6990     * is a good fit. For example, announcing a new page in a book. If accessibility
6991     * is not enabled this method does nothing.
6992     *
6993     * @param text The announcement text.
6994     */
6995    public void announceForAccessibility(CharSequence text) {
6996        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
6997            AccessibilityEvent event = AccessibilityEvent.obtain(
6998                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
6999            onInitializeAccessibilityEvent(event);
7000            event.getText().add(text);
7001            event.setContentDescription(null);
7002            mParent.requestSendAccessibilityEvent(this, event);
7003        }
7004    }
7005
7006    /**
7007     * @see #sendAccessibilityEvent(int)
7008     *
7009     * Note: Called from the default {@link AccessibilityDelegate}.
7010     *
7011     * @hide
7012     */
7013    public void sendAccessibilityEventInternal(int eventType) {
7014        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
7015            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
7016        }
7017    }
7018
7019    /**
7020     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
7021     * takes as an argument an empty {@link AccessibilityEvent} and does not
7022     * perform a check whether accessibility is enabled.
7023     * <p>
7024     * If an {@link AccessibilityDelegate} has been specified via calling
7025     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7026     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
7027     * is responsible for handling this call.
7028     * </p>
7029     *
7030     * @param event The event to send.
7031     *
7032     * @see #sendAccessibilityEvent(int)
7033     */
7034    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
7035        if (mAccessibilityDelegate != null) {
7036            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
7037        } else {
7038            sendAccessibilityEventUncheckedInternal(event);
7039        }
7040    }
7041
7042    /**
7043     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
7044     *
7045     * Note: Called from the default {@link AccessibilityDelegate}.
7046     *
7047     * @hide
7048     */
7049    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
7050        if (!isShown()) {
7051            return;
7052        }
7053        onInitializeAccessibilityEvent(event);
7054        // Only a subset of accessibility events populates text content.
7055        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
7056            dispatchPopulateAccessibilityEvent(event);
7057        }
7058        // In the beginning we called #isShown(), so we know that getParent() is not null.
7059        ViewParent parent = getParent();
7060        if (parent != null) {
7061            getParent().requestSendAccessibilityEvent(this, event);
7062        }
7063    }
7064
7065    /**
7066     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
7067     * to its children for adding their text content to the event. Note that the
7068     * event text is populated in a separate dispatch path since we add to the
7069     * event not only the text of the source but also the text of all its descendants.
7070     * A typical implementation will call
7071     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
7072     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7073     * on each child. Override this method if custom population of the event text
7074     * content is required.
7075     * <p>
7076     * If an {@link AccessibilityDelegate} has been specified via calling
7077     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7078     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
7079     * is responsible for handling this call.
7080     * </p>
7081     * <p>
7082     * <em>Note:</em> Accessibility events of certain types are not dispatched for
7083     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
7084     * </p>
7085     *
7086     * @param event The event.
7087     *
7088     * @return True if the event population was completed.
7089     */
7090    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
7091        if (mAccessibilityDelegate != null) {
7092            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
7093        } else {
7094            return dispatchPopulateAccessibilityEventInternal(event);
7095        }
7096    }
7097
7098    /**
7099     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7100     *
7101     * Note: Called from the default {@link AccessibilityDelegate}.
7102     *
7103     * @hide
7104     */
7105    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7106        onPopulateAccessibilityEvent(event);
7107        return false;
7108    }
7109
7110    /**
7111     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
7112     * giving a chance to this View to populate the accessibility event with its
7113     * text content. While this method is free to modify event
7114     * attributes other than text content, doing so should normally be performed in
7115     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
7116     * <p>
7117     * Example: Adding formatted date string to an accessibility event in addition
7118     *          to the text added by the super implementation:
7119     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7120     *     super.onPopulateAccessibilityEvent(event);
7121     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
7122     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
7123     *         mCurrentDate.getTimeInMillis(), flags);
7124     *     event.getText().add(selectedDateUtterance);
7125     * }</pre>
7126     * <p>
7127     * If an {@link AccessibilityDelegate} has been specified via calling
7128     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7129     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
7130     * is responsible for handling this call.
7131     * </p>
7132     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7133     * information to the event, in case the default implementation has basic information to add.
7134     * </p>
7135     *
7136     * @param event The accessibility event which to populate.
7137     *
7138     * @see #sendAccessibilityEvent(int)
7139     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7140     */
7141    @CallSuper
7142    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
7143        if (mAccessibilityDelegate != null) {
7144            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
7145        } else {
7146            onPopulateAccessibilityEventInternal(event);
7147        }
7148    }
7149
7150    /**
7151     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
7152     *
7153     * Note: Called from the default {@link AccessibilityDelegate}.
7154     *
7155     * @hide
7156     */
7157    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
7158    }
7159
7160    /**
7161     * Initializes an {@link AccessibilityEvent} with information about
7162     * this View which is the event source. In other words, the source of
7163     * an accessibility event is the view whose state change triggered firing
7164     * the event.
7165     * <p>
7166     * Example: Setting the password property of an event in addition
7167     *          to properties set by the super implementation:
7168     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7169     *     super.onInitializeAccessibilityEvent(event);
7170     *     event.setPassword(true);
7171     * }</pre>
7172     * <p>
7173     * If an {@link AccessibilityDelegate} has been specified via calling
7174     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7175     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
7176     * is responsible for handling this call.
7177     * </p>
7178     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
7179     * information to the event, in case the default implementation has basic information to add.
7180     * </p>
7181     * @param event The event to initialize.
7182     *
7183     * @see #sendAccessibilityEvent(int)
7184     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
7185     */
7186    @CallSuper
7187    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
7188        if (mAccessibilityDelegate != null) {
7189            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
7190        } else {
7191            onInitializeAccessibilityEventInternal(event);
7192        }
7193    }
7194
7195    /**
7196     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
7197     *
7198     * Note: Called from the default {@link AccessibilityDelegate}.
7199     *
7200     * @hide
7201     */
7202    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
7203        event.setSource(this);
7204        event.setClassName(getAccessibilityClassName());
7205        event.setPackageName(getContext().getPackageName());
7206        event.setEnabled(isEnabled());
7207        event.setContentDescription(mContentDescription);
7208
7209        switch (event.getEventType()) {
7210            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
7211                ArrayList<View> focusablesTempList = (mAttachInfo != null)
7212                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
7213                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
7214                event.setItemCount(focusablesTempList.size());
7215                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
7216                if (mAttachInfo != null) {
7217                    focusablesTempList.clear();
7218                }
7219            } break;
7220            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
7221                CharSequence text = getIterableTextForAccessibility();
7222                if (text != null && text.length() > 0) {
7223                    event.setFromIndex(getAccessibilitySelectionStart());
7224                    event.setToIndex(getAccessibilitySelectionEnd());
7225                    event.setItemCount(text.length());
7226                }
7227            } break;
7228        }
7229    }
7230
7231    /**
7232     * Returns an {@link AccessibilityNodeInfo} representing this view from the
7233     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
7234     * This method is responsible for obtaining an accessibility node info from a
7235     * pool of reusable instances and calling
7236     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
7237     * initialize the former.
7238     * <p>
7239     * Note: The client is responsible for recycling the obtained instance by calling
7240     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
7241     * </p>
7242     *
7243     * @return A populated {@link AccessibilityNodeInfo}.
7244     *
7245     * @see AccessibilityNodeInfo
7246     */
7247    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
7248        if (mAccessibilityDelegate != null) {
7249            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
7250        } else {
7251            return createAccessibilityNodeInfoInternal();
7252        }
7253    }
7254
7255    /**
7256     * @see #createAccessibilityNodeInfo()
7257     *
7258     * @hide
7259     */
7260    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
7261        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7262        if (provider != null) {
7263            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
7264        } else {
7265            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
7266            onInitializeAccessibilityNodeInfo(info);
7267            return info;
7268        }
7269    }
7270
7271    /**
7272     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
7273     * The base implementation sets:
7274     * <ul>
7275     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
7276     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
7277     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
7278     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
7279     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
7280     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
7281     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
7282     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
7283     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
7284     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
7285     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
7286     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
7287     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
7288     * </ul>
7289     * <p>
7290     * Subclasses should override this method, call the super implementation,
7291     * and set additional attributes.
7292     * </p>
7293     * <p>
7294     * If an {@link AccessibilityDelegate} has been specified via calling
7295     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7296     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
7297     * is responsible for handling this call.
7298     * </p>
7299     *
7300     * @param info The instance to initialize.
7301     */
7302    @CallSuper
7303    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
7304        if (mAccessibilityDelegate != null) {
7305            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
7306        } else {
7307            onInitializeAccessibilityNodeInfoInternal(info);
7308        }
7309    }
7310
7311    /**
7312     * Gets the location of this view in screen coordinates.
7313     *
7314     * @param outRect The output location
7315     * @hide
7316     */
7317    public void getBoundsOnScreen(Rect outRect) {
7318        getBoundsOnScreen(outRect, false);
7319    }
7320
7321    /**
7322     * Gets the location of this view in screen coordinates.
7323     *
7324     * @param outRect The output location
7325     * @param clipToParent Whether to clip child bounds to the parent ones.
7326     * @hide
7327     */
7328    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
7329        if (mAttachInfo == null) {
7330            return;
7331        }
7332
7333        RectF position = mAttachInfo.mTmpTransformRect;
7334        position.set(0, 0, mRight - mLeft, mBottom - mTop);
7335        mapRectFromViewToScreenCoords(position, clipToParent);
7336        outRect.set(Math.round(position.left), Math.round(position.top),
7337                Math.round(position.right), Math.round(position.bottom));
7338    }
7339
7340    /**
7341     * Map a rectangle from view-relative coordinates to screen-relative coordinates
7342     *
7343     * @param rect The rectangle to be mapped
7344     * @param clipToParent Whether to clip child bounds to the parent ones.
7345     * @hide
7346     */
7347    public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {
7348        if (!hasIdentityMatrix()) {
7349            getMatrix().mapRect(rect);
7350        }
7351
7352        rect.offset(mLeft, mTop);
7353
7354        ViewParent parent = mParent;
7355        while (parent instanceof View) {
7356            View parentView = (View) parent;
7357
7358            rect.offset(-parentView.mScrollX, -parentView.mScrollY);
7359
7360            if (clipToParent) {
7361                rect.left = Math.max(rect.left, 0);
7362                rect.top = Math.max(rect.top, 0);
7363                rect.right = Math.min(rect.right, parentView.getWidth());
7364                rect.bottom = Math.min(rect.bottom, parentView.getHeight());
7365            }
7366
7367            if (!parentView.hasIdentityMatrix()) {
7368                parentView.getMatrix().mapRect(rect);
7369            }
7370
7371            rect.offset(parentView.mLeft, parentView.mTop);
7372
7373            parent = parentView.mParent;
7374        }
7375
7376        if (parent instanceof ViewRootImpl) {
7377            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
7378            rect.offset(0, -viewRootImpl.mCurScrollY);
7379        }
7380
7381        rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
7382    }
7383
7384    /**
7385     * Return the class name of this object to be used for accessibility purposes.
7386     * Subclasses should only override this if they are implementing something that
7387     * should be seen as a completely new class of view when used by accessibility,
7388     * unrelated to the class it is deriving from.  This is used to fill in
7389     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
7390     */
7391    public CharSequence getAccessibilityClassName() {
7392        return View.class.getName();
7393    }
7394
7395    /**
7396     * Called when assist structure is being retrieved from a view as part of
7397     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
7398     * @param structure Fill in with structured view data.  The default implementation
7399     * fills in all data that can be inferred from the view itself.
7400     */
7401    public void onProvideStructure(ViewStructure structure) {
7402        onProvideStructureForAssistOrAutofill(structure, false, 0);
7403    }
7404
7405    /**
7406     * Populates a {@link ViewStructure} to fullfil an autofill request.
7407     *
7408     * <p>The structure should contain at least the following properties:
7409     * <ul>
7410     *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
7411     *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
7412     *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
7413     *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
7414     * </ul>
7415     *
7416     * <p>It's also recommended to set the following properties - the more properties the structure
7417     * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
7418     * using the structure:
7419     *
7420     * <ul>
7421     *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
7422     *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
7423     *       view can only be filled with predefined values (typically used when the autofill type
7424     *       is {@link #AUTOFILL_TYPE_LIST}).
7425     *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
7426     *   <li>Class name ({@link ViewStructure#setClassName(String)}).
7427     *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
7428     *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
7429     *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
7430     *       opacity ({@link ViewStructure#setOpaque(boolean)}).
7431     *   <li>For views representing text fields, text properties such as the text itself
7432     *       ({@link ViewStructure#setText(CharSequence)}), text hints
7433     *       ({@link ViewStructure#setHint(CharSequence)}, input type
7434     *       ({@link ViewStructure#setInputType(int)}),
7435     *   <li>For views representing HTML nodes, its web domain
7436     *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
7437     *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
7438     * </ul>
7439     *
7440     * <p>The default implementation of this method already sets most of these properties based on
7441     * related {@link View} methods (for example, the autofill id is set using
7442     * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
7443     * and views in the standard Android widgets library also override it to set their
7444     * relevant properties (for example, {@link android.widget.TextView} already sets the text
7445     * properties), so it's recommended to only override this method
7446     * (and call {@code super.onProvideAutofillStructure()}) when:
7447     *
7448     * <ul>
7449     *   <li>The view contents does not include PII (Personally Identifiable Information), so it
7450     *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
7451     *   <li>The view can only be autofilled with predefined options, so it can call
7452     *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
7453     * </ul>
7454     *
7455     * <p><b>NOTE:</b> the {@code left} and {@code top} values set in
7456     * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
7457     * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
7458     *
7459     * <p>Views support the Autofill Framework mainly by:
7460     * <ul>
7461     *   <li>Providing the metadata defining what the view means and how it can be autofilled.
7462     *   <li>Notifying the Android System when the view value changed by calling
7463     *       {@link AutofillManager#notifyValueChanged(View)}.
7464     *   <li>Implementing the methods that autofill the view.
7465     * </ul>
7466     * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
7467     * for the latter.
7468     *
7469     * @param structure fill in with structured view data for autofill purposes.
7470     * @param flags optional flags.
7471     *
7472     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7473     */
7474    public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
7475        onProvideStructureForAssistOrAutofill(structure, true, flags);
7476    }
7477
7478    private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
7479            boolean forAutofill, @AutofillFlags int flags) {
7480        final int id = mID;
7481        if (id != NO_ID && !isViewIdGenerated(id)) {
7482            String pkg, type, entry;
7483            try {
7484                final Resources res = getResources();
7485                entry = res.getResourceEntryName(id);
7486                type = res.getResourceTypeName(id);
7487                pkg = res.getResourcePackageName(id);
7488            } catch (Resources.NotFoundException e) {
7489                entry = type = pkg = null;
7490            }
7491            structure.setId(id, pkg, type, entry);
7492        } else {
7493            structure.setId(id, null, null, null);
7494        }
7495
7496        if (forAutofill) {
7497            final @AutofillType int autofillType = getAutofillType();
7498            // Don't need to fill autofill info if view does not support it.
7499            // For example, only TextViews that are editable support autofill
7500            if (autofillType != AUTOFILL_TYPE_NONE) {
7501                structure.setAutofillType(autofillType);
7502                structure.setAutofillHints(getAutofillHints());
7503                structure.setAutofillValue(getAutofillValue());
7504            }
7505        }
7506
7507        int ignoredParentLeft = 0;
7508        int ignoredParentTop = 0;
7509        if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
7510            View parentGroup = null;
7511
7512            ViewParent viewParent = getParent();
7513            if (viewParent instanceof View) {
7514                parentGroup = (View) viewParent;
7515            }
7516
7517            while (parentGroup != null && !parentGroup.isImportantForAutofill()) {
7518                ignoredParentLeft += parentGroup.mLeft;
7519                ignoredParentTop += parentGroup.mTop;
7520
7521                viewParent = parentGroup.getParent();
7522                if (viewParent instanceof View) {
7523                    parentGroup = (View) viewParent;
7524                } else {
7525                    break;
7526                }
7527            }
7528        }
7529
7530        structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
7531                mRight - mLeft, mBottom - mTop);
7532        if (!forAutofill) {
7533            if (!hasIdentityMatrix()) {
7534                structure.setTransformation(getMatrix());
7535            }
7536            structure.setElevation(getZ());
7537        }
7538        structure.setVisibility(getVisibility());
7539        structure.setEnabled(isEnabled());
7540        if (isClickable()) {
7541            structure.setClickable(true);
7542        }
7543        if (isFocusable()) {
7544            structure.setFocusable(true);
7545        }
7546        if (isFocused()) {
7547            structure.setFocused(true);
7548        }
7549        if (isAccessibilityFocused()) {
7550            structure.setAccessibilityFocused(true);
7551        }
7552        if (isSelected()) {
7553            structure.setSelected(true);
7554        }
7555        if (isActivated()) {
7556            structure.setActivated(true);
7557        }
7558        if (isLongClickable()) {
7559            structure.setLongClickable(true);
7560        }
7561        if (this instanceof Checkable) {
7562            structure.setCheckable(true);
7563            if (((Checkable)this).isChecked()) {
7564                structure.setChecked(true);
7565            }
7566        }
7567        if (isOpaque()) {
7568            structure.setOpaque(true);
7569        }
7570        if (isContextClickable()) {
7571            structure.setContextClickable(true);
7572        }
7573        structure.setClassName(getAccessibilityClassName().toString());
7574        structure.setContentDescription(getContentDescription());
7575    }
7576
7577    /**
7578     * Called when assist structure is being retrieved from a view as part of
7579     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
7580     * generate additional virtual structure under this view.  The defaullt implementation
7581     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
7582     * view's virtual accessibility nodes, if any.  You can override this for a more
7583     * optimal implementation providing this data.
7584     */
7585    public void onProvideVirtualStructure(ViewStructure structure) {
7586        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
7587        if (provider != null) {
7588            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
7589            structure.setChildCount(1);
7590            ViewStructure root = structure.newChild(0);
7591            populateVirtualStructure(root, provider, info);
7592            info.recycle();
7593        }
7594    }
7595
7596    /**
7597     * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
7598     * request.
7599     *
7600     * <p>This method should be used when the view manages a virtual structure under this view. For
7601     * example, a view that draws input fields using {@link #draw(Canvas)}.
7602     *
7603     * <p>When implementing this method, subclasses must follow the rules below:
7604     *
7605     * <ul>
7606     *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
7607     *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
7608     *       identifying the children in the virtual structure.
7609     *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
7610     *       exclude intermediate levels that are irrelevant for autofill; that would improve the
7611     *       autofill performance.
7612     *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
7613     *       children.
7614     *   <li>Set the autofill properties of the child structure as defined by
7615     *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
7616     *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
7617     *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
7618     *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
7619     *       when the focused virtual child changed.
7620     *   <li>Call
7621     *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
7622     *       when the value of a virtual child changed.
7623     *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
7624     *       changed and the current context should be committed (for example, when the user tapped
7625     *       a {@code SUBMIT} button in an HTML page).
7626     *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
7627     *       changed and the current context should be canceled (for example, when the user tapped
7628     *       a {@code CANCEL} button in an HTML page).
7629     *   <li>Provide ways for users to manually request autofill by calling
7630     *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
7631     *   <li>The {@code left} and {@code top} values set in
7632     *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
7633     *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
7634     *       structure.
7635     * </ul>
7636     *
7637     * <p>Views with virtual children support the Autofill Framework mainly by:
7638     * <ul>
7639     *   <li>Providing the metadata defining what the virtual children mean and how they can be
7640     *       autofilled.
7641     *   <li>Implementing the methods that autofill the virtual children.
7642     * </ul>
7643     * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
7644     * for the latter.
7645     *
7646     * @param structure fill in with virtual children data for autofill purposes.
7647     * @param flags optional flags.
7648     *
7649     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
7650     */
7651    public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
7652    }
7653
7654    /**
7655     * Automatically fills the content of this view with the {@code value}.
7656     *
7657     * <p>Views support the Autofill Framework mainly by:
7658     * <ul>
7659     *   <li>Providing the metadata defining what the view means and how it can be autofilled.
7660     *   <li>Implementing the methods that autofill the view.
7661     * </ul>
7662     * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
7663     * this method is responsible for latter.
7664     *
7665     * <p>This method does nothing by default, but when overridden it typically:
7666     * <ol>
7667     *   <li>Checks if the provided value matches the expected type (which is defined by
7668     *       {@link #getAutofillType()}).
7669     *   <li>Checks if the view is editable - if it isn't, it should return right away.
7670     *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
7671     *   <li>Pass the actual value to the equivalent setter in the view.
7672     * </ol>
7673     *
7674     * <p>For example, a text-field view could implement the method this way:
7675     *
7676     * <pre class="prettyprint">
7677     * &#64;Override
7678     * public void autofill(AutofillValue value) {
7679     *   if (!value.isText() || !this.isEditable()) {
7680     *      return;
7681     *   }
7682     *   CharSequence text = value.getTextValue();
7683     *   if (text != null) {
7684     *     this.setText(text);
7685     *   }
7686     * }
7687     * </pre>
7688     *
7689     * <p>If the value is updated asynchronously, the next call to
7690     * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
7691     * changed to the autofilled value. If not, the view will not be considered autofilled.
7692     *
7693     * @param value value to be autofilled.
7694     */
7695    public void autofill(@SuppressWarnings("unused") AutofillValue value) {
7696    }
7697
7698    /**
7699     * Automatically fills the content of the virtual children within this view.
7700     *
7701     * <p>Views with virtual children support the Autofill Framework mainly by:
7702     * <ul>
7703     *   <li>Providing the metadata defining what the virtual children mean and how they can be
7704     *       autofilled.
7705     *   <li>Implementing the methods that autofill the virtual children.
7706     * </ul>
7707     * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
7708     * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
7709     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
7710     *
7711     * <p>If a child value is updated asynchronously, the next call to
7712     * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen
7713     * <b>after</b> the value was changed to the autofilled value. If not, the child will not be
7714     * considered autofilled.
7715     *
7716     * <p><b>NOTE:</b> to indicate that a virtual view was autofilled,
7717     * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
7718     * changes.
7719     *
7720     * @param values map of values to be autofilled, keyed by virtual child id.
7721     *
7722     * @attr ref android.R.styleable#Theme_autofilledHighlight
7723     */
7724    public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) {
7725    }
7726
7727    /**
7728     * Gets the unique identifier of this view in the screen, for autofill purposes.
7729     *
7730     * @return The View's autofill id.
7731     */
7732    public final AutofillId getAutofillId() {
7733        if (mAutofillId == null) {
7734            // The autofill id needs to be unique, but its value doesn't matter,
7735            // so it's better to reuse the accessibility id to save space.
7736            mAutofillId = new AutofillId(getAutofillViewId());
7737        }
7738        return mAutofillId;
7739    }
7740
7741    /**
7742     * Describes the autofill type of this view, so an
7743     * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
7744     * when autofilling the view.
7745     *
7746     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
7747     * support the Autofill Framework.
7748     *
7749     * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
7750     * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
7751     *
7752     * @see #onProvideAutofillStructure(ViewStructure, int)
7753     * @see #autofill(AutofillValue)
7754     */
7755    public @AutofillType int getAutofillType() {
7756        return AUTOFILL_TYPE_NONE;
7757    }
7758
7759    /**
7760     * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
7761     * to autofill the view with the user's data.
7762     *
7763     * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
7764     *
7765     * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
7766     * {@code null} if no hints were set.
7767     *
7768     * @attr ref android.R.styleable#View_autofillHints
7769     */
7770    @ViewDebug.ExportedProperty()
7771    @Nullable public String[] getAutofillHints() {
7772        return mAutofillHints;
7773    }
7774
7775    /**
7776     * @hide
7777     */
7778    public boolean isAutofilled() {
7779        return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
7780    }
7781
7782    /**
7783     * Gets the {@link View}'s current autofill value.
7784     *
7785     * <p>By default returns {@code null}, but views should override it to properly support the
7786     * Autofill Framework.
7787     *
7788     * @see #onProvideAutofillStructure(ViewStructure, int)
7789     * @see #autofill(AutofillValue)
7790     */
7791    @Nullable
7792    public AutofillValue getAutofillValue() {
7793        return null;
7794    }
7795
7796    /**
7797     * Gets the mode for determining whether this view is important for autofill.
7798     *
7799     * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
7800     * info about this mode.
7801     *
7802     * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
7803     * {@link #setImportantForAutofill(int)}.
7804     *
7805     * @attr ref android.R.styleable#View_importantForAutofill
7806     */
7807    @ViewDebug.ExportedProperty(mapping = {
7808            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"),
7809            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"),
7810            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"),
7811            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS,
7812                to = "yesExcludeDescendants"),
7813            @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS,
7814                to = "noExcludeDescendants")})
7815    public @AutofillImportance int getImportantForAutofill() {
7816        return (mPrivateFlags3
7817                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT;
7818    }
7819
7820    /**
7821     * Sets the mode for determining whether this view is considered important for autofill.
7822     *
7823     * <p>The platform determines the importance for autofill automatically but you
7824     * can use this method to customize the behavior. For example:
7825     *
7826     * <ol>
7827     *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
7828     *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
7829     *   <li>When both the view and its children are irrelevant for autofill (for example, the root
7830     *       view of an activity containing a spreadhseet editor), it should be
7831     *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7832     *   <li>When the view content is relevant for autofill but its children aren't (for example,
7833     *       a credit card expiration date represented by a custom view that overrides the proper
7834     *       autofill methods and has 2 children representing the month and year), it should
7835     *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
7836     * </ol>
7837     *
7838     * <p><b>NOTE:</strong> setting the mode as does {@link #IMPORTANT_FOR_AUTOFILL_NO} or
7839     * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
7840     * children) will be always be considered not important; for example, when the user explicitly
7841     * makes an autofill request, all views are considered important. See
7842     * {@link #isImportantForAutofill()} for more details about how the View's importance for
7843     * autofill is used.
7844     *
7845     * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
7846     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
7847     * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
7848     *
7849     * @attr ref android.R.styleable#View_importantForAutofill
7850     */
7851    public void setImportantForAutofill(@AutofillImportance int mode) {
7852        mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7853        mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT)
7854                & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK;
7855    }
7856
7857    /**
7858     * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
7859     * associated with this view is considered important for autofill purposes.
7860     *
7861     * <p>Generally speaking, a view is important for autofill if:
7862     * <ol>
7863     * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
7864     * <li>The view contents can help an {@link android.service.autofill.AutofillService}
7865     *     determine how other views can be autofilled.
7866     * <ol>
7867     *
7868     * <p>For example, view containers should typically return {@code false} for performance reasons
7869     * (since the important info is provided by their children), but if its properties have relevant
7870     * information (for example, a resource id called {@code credentials}, it should return
7871     * {@code true}. On the other hand, views representing labels or editable fields should
7872     * typically return {@code true}, but in some cases they could return {@code false}
7873     * (for example, if they're part of a "Captcha" mechanism).
7874     *
7875     * <p>The value returned by this method depends on the value returned by
7876     * {@link #getImportantForAutofill()}:
7877     *
7878     * <ol>
7879     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
7880     *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
7881     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
7882     *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
7883     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
7884     *       that can return {@code true} in some cases (like a container with a resource id),
7885     *       but {@code false} in most.
7886     *   <li>otherwise, it returns {@code false}.
7887     * </ol>
7888     *
7889     * <p>When a view is considered important for autofill:
7890     * <ul>
7891     *   <li>The view might automatically trigger an autofill request when focused on.
7892     *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
7893     *       request.
7894     * </ul>
7895     *
7896     * <p>On the other hand, when a view is considered not important for autofill:
7897     * <ul>
7898     *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
7899     *       request through {@link AutofillManager#requestAutofill(View)}.
7900     *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
7901     *       autofill request, unless the request has the
7902     *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
7903     * </ul>
7904     *
7905     * @return whether the view is considered important for autofill.
7906     *
7907     * @see #setImportantForAutofill(int)
7908     * @see #IMPORTANT_FOR_AUTOFILL_AUTO
7909     * @see #IMPORTANT_FOR_AUTOFILL_YES
7910     * @see #IMPORTANT_FOR_AUTOFILL_NO
7911     * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7912     * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7913     * @see AutofillManager#requestAutofill(View)
7914     */
7915    public final boolean isImportantForAutofill() {
7916        // Check parent mode to ensure we're not hidden.
7917        ViewParent parent = mParent;
7918        while (parent instanceof View) {
7919            final int parentImportance = ((View) parent).getImportantForAutofill();
7920            if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7921                    || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
7922                return false;
7923            }
7924            parent = parent.getParent();
7925        }
7926
7927        final int importance = getImportantForAutofill();
7928
7929        // First, check the explicit states.
7930        if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
7931                || importance == IMPORTANT_FOR_AUTOFILL_YES) {
7932            return true;
7933        }
7934        if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
7935                || importance == IMPORTANT_FOR_AUTOFILL_NO) {
7936            return false;
7937        }
7938
7939        // Then use some heuristics to handle AUTO.
7940
7941        // Always include views that have an explicit resource id.
7942        final int id = mID;
7943        if (id != NO_ID && !isViewIdGenerated(id)) {
7944            final Resources res = getResources();
7945            String entry = null;
7946            String pkg = null;
7947            try {
7948                entry = res.getResourceEntryName(id);
7949                pkg = res.getResourcePackageName(id);
7950            } catch (Resources.NotFoundException e) {
7951                // ignore
7952            }
7953            if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) {
7954                return true;
7955            }
7956        }
7957
7958        // Otherwise, assume it's not important...
7959        return false;
7960    }
7961
7962    @Nullable
7963    private AutofillManager getAutofillManager() {
7964        return mContext.getSystemService(AutofillManager.class);
7965    }
7966
7967    private boolean isAutofillable() {
7968        return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill()
7969                && getAutofillViewId() > LAST_APP_AUTOFILL_ID;
7970    }
7971
7972    private void populateVirtualStructure(ViewStructure structure,
7973            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
7974        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
7975                null, null, null);
7976        Rect rect = structure.getTempRect();
7977        info.getBoundsInParent(rect);
7978        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
7979        structure.setVisibility(VISIBLE);
7980        structure.setEnabled(info.isEnabled());
7981        if (info.isClickable()) {
7982            structure.setClickable(true);
7983        }
7984        if (info.isFocusable()) {
7985            structure.setFocusable(true);
7986        }
7987        if (info.isFocused()) {
7988            structure.setFocused(true);
7989        }
7990        if (info.isAccessibilityFocused()) {
7991            structure.setAccessibilityFocused(true);
7992        }
7993        if (info.isSelected()) {
7994            structure.setSelected(true);
7995        }
7996        if (info.isLongClickable()) {
7997            structure.setLongClickable(true);
7998        }
7999        if (info.isCheckable()) {
8000            structure.setCheckable(true);
8001            if (info.isChecked()) {
8002                structure.setChecked(true);
8003            }
8004        }
8005        if (info.isContextClickable()) {
8006            structure.setContextClickable(true);
8007        }
8008        CharSequence cname = info.getClassName();
8009        structure.setClassName(cname != null ? cname.toString() : null);
8010        structure.setContentDescription(info.getContentDescription());
8011        if ((info.getText() != null || info.getError() != null)) {
8012            structure.setText(info.getText(), info.getTextSelectionStart(),
8013                    info.getTextSelectionEnd());
8014        }
8015        final int NCHILDREN = info.getChildCount();
8016        if (NCHILDREN > 0) {
8017            structure.setChildCount(NCHILDREN);
8018            for (int i=0; i<NCHILDREN; i++) {
8019                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
8020                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
8021                ViewStructure child = structure.newChild(i);
8022                populateVirtualStructure(child, provider, cinfo);
8023                cinfo.recycle();
8024            }
8025        }
8026    }
8027
8028    /**
8029     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
8030     * implementation calls {@link #onProvideStructure} and
8031     * {@link #onProvideVirtualStructure}.
8032     */
8033    public void dispatchProvideStructure(ViewStructure structure) {
8034        dispatchProvideStructureForAssistOrAutofill(structure, false, 0);
8035    }
8036
8037    /**
8038     * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
8039     * when an Assist structure is being created as part of an autofill request.
8040     *
8041     * <p>The default implementation does the following:
8042     * <ul>
8043     *   <li>Sets the {@link AutofillId} in the structure.
8044     *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
8045     *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
8046     * </ul>
8047     *
8048     * <p>Typically, this method should only be overridden by subclasses that provide a view
8049     * hierarchy (such as {@link ViewGroup}) - other classes should override
8050     * {@link #onProvideAutofillStructure(ViewStructure, int)} or
8051     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
8052     *
8053     * <p>When overridden, it must:
8054     *
8055     * <ul>
8056     *   <li>Either call
8057     *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
8058     *       set the {@link AutofillId} in the structure (for example, by calling
8059     *       {@code structure.setAutofillId(getAutofillId())}).
8060     *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
8061     *       set, all views in the structure should be considered important for autofill,
8062     *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
8063     *       respect this flag to provide a better user experience - this flag is typically used
8064     *       when an user explicitly requested autofill. If the flag is not set,
8065     *       then only views marked as important for autofill should be included in the
8066     *       structure - skipping non-important views optimizes the overall autofill performance.
8067     * </ul>
8068     *
8069     * @param structure fill in with structured view data for autofill purposes.
8070     * @param flags optional flags.
8071     *
8072     * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
8073     */
8074    public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
8075            @AutofillFlags int flags) {
8076        dispatchProvideStructureForAssistOrAutofill(structure, true, flags);
8077    }
8078
8079    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
8080            boolean forAutofill, @AutofillFlags int flags) {
8081        if (forAutofill) {
8082            structure.setAutofillId(getAutofillId());
8083            if (!isLaidOut()) {
8084                Log.w(VIEW_LOG_TAG, "dispatchProvideAutofillStructure(): not laid out, ignoring");
8085                return;
8086            }
8087            onProvideAutofillStructure(structure, flags);
8088            onProvideAutofillVirtualStructure(structure, flags);
8089        } else if (!isAssistBlocked()) {
8090            onProvideStructure(structure);
8091            onProvideVirtualStructure(structure);
8092        } else {
8093            structure.setClassName(getAccessibilityClassName().toString());
8094            structure.setAssistBlocked(true);
8095        }
8096    }
8097
8098    /**
8099     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
8100     *
8101     * Note: Called from the default {@link AccessibilityDelegate}.
8102     *
8103     * @hide
8104     */
8105    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
8106        if (mAttachInfo == null) {
8107            return;
8108        }
8109
8110        Rect bounds = mAttachInfo.mTmpInvalRect;
8111
8112        getDrawingRect(bounds);
8113        info.setBoundsInParent(bounds);
8114
8115        getBoundsOnScreen(bounds, true);
8116        info.setBoundsInScreen(bounds);
8117
8118        ViewParent parent = getParentForAccessibility();
8119        if (parent instanceof View) {
8120            info.setParent((View) parent);
8121        }
8122
8123        if (mID != View.NO_ID) {
8124            View rootView = getRootView();
8125            if (rootView == null) {
8126                rootView = this;
8127            }
8128
8129            View label = rootView.findLabelForView(this, mID);
8130            if (label != null) {
8131                info.setLabeledBy(label);
8132            }
8133
8134            if ((mAttachInfo.mAccessibilityFetchFlags
8135                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
8136                    && Resources.resourceHasPackage(mID)) {
8137                try {
8138                    String viewId = getResources().getResourceName(mID);
8139                    info.setViewIdResourceName(viewId);
8140                } catch (Resources.NotFoundException nfe) {
8141                    /* ignore */
8142                }
8143            }
8144        }
8145
8146        if (mLabelForId != View.NO_ID) {
8147            View rootView = getRootView();
8148            if (rootView == null) {
8149                rootView = this;
8150            }
8151            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
8152            if (labeled != null) {
8153                info.setLabelFor(labeled);
8154            }
8155        }
8156
8157        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
8158            View rootView = getRootView();
8159            if (rootView == null) {
8160                rootView = this;
8161            }
8162            View next = rootView.findViewInsideOutShouldExist(this,
8163                    mAccessibilityTraversalBeforeId);
8164            if (next != null && next.includeForAccessibility()) {
8165                info.setTraversalBefore(next);
8166            }
8167        }
8168
8169        if (mAccessibilityTraversalAfterId != View.NO_ID) {
8170            View rootView = getRootView();
8171            if (rootView == null) {
8172                rootView = this;
8173            }
8174            View next = rootView.findViewInsideOutShouldExist(this,
8175                    mAccessibilityTraversalAfterId);
8176            if (next != null && next.includeForAccessibility()) {
8177                info.setTraversalAfter(next);
8178            }
8179        }
8180
8181        info.setVisibleToUser(isVisibleToUser());
8182
8183        info.setImportantForAccessibility(isImportantForAccessibility());
8184        info.setPackageName(mContext.getPackageName());
8185        info.setClassName(getAccessibilityClassName());
8186        info.setContentDescription(getContentDescription());
8187
8188        info.setEnabled(isEnabled());
8189        info.setClickable(isClickable());
8190        info.setFocusable(isFocusable());
8191        info.setFocused(isFocused());
8192        info.setAccessibilityFocused(isAccessibilityFocused());
8193        info.setSelected(isSelected());
8194        info.setLongClickable(isLongClickable());
8195        info.setContextClickable(isContextClickable());
8196        info.setLiveRegion(getAccessibilityLiveRegion());
8197
8198        // TODO: These make sense only if we are in an AdapterView but all
8199        // views can be selected. Maybe from accessibility perspective
8200        // we should report as selectable view in an AdapterView.
8201        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
8202        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
8203
8204        if (isFocusable()) {
8205            if (isFocused()) {
8206                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
8207            } else {
8208                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
8209            }
8210        }
8211
8212        if (!isAccessibilityFocused()) {
8213            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
8214        } else {
8215            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
8216        }
8217
8218        if (isClickable() && isEnabled()) {
8219            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
8220        }
8221
8222        if (isLongClickable() && isEnabled()) {
8223            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
8224        }
8225
8226        if (isContextClickable() && isEnabled()) {
8227            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
8228        }
8229
8230        CharSequence text = getIterableTextForAccessibility();
8231        if (text != null && text.length() > 0) {
8232            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
8233
8234            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
8235            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
8236            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
8237            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
8238                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
8239                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
8240        }
8241
8242        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
8243        populateAccessibilityNodeInfoDrawingOrderInParent(info);
8244    }
8245
8246    /**
8247     * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
8248     * additional data.
8249     * <p>
8250     * This method only needs overloading if the node is marked as having extra data available.
8251     * </p>
8252     *
8253     * @param info The info to which to add the extra data. Never {@code null}.
8254     * @param extraDataKey A key specifying the type of extra data to add to the info. The
8255     *                     extra data should be added to the {@link Bundle} returned by
8256     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
8257     *                     {@code null}.
8258     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
8259     *                  {@code null} if the service provided no arguments.
8260     *
8261     * @see AccessibilityNodeInfo#setAvailableExtraData(List)
8262     */
8263    public void addExtraDataToAccessibilityNodeInfo(
8264            @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
8265            @Nullable Bundle arguments) {
8266    }
8267
8268    /**
8269     * Determine the order in which this view will be drawn relative to its siblings for a11y
8270     *
8271     * @param info The info whose drawing order should be populated
8272     */
8273    private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) {
8274        /*
8275         * If the view's bounds haven't been set yet, layout has not completed. In that situation,
8276         * drawing order may not be well-defined, and some Views with custom drawing order may
8277         * not be initialized sufficiently to respond properly getChildDrawingOrder.
8278         */
8279        if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) {
8280            info.setDrawingOrder(0);
8281            return;
8282        }
8283        int drawingOrderInParent = 1;
8284        // Iterate up the hierarchy if parents are not important for a11y
8285        View viewAtDrawingLevel = this;
8286        final ViewParent parent = getParentForAccessibility();
8287        while (viewAtDrawingLevel != parent) {
8288            final ViewParent currentParent = viewAtDrawingLevel.getParent();
8289            if (!(currentParent instanceof ViewGroup)) {
8290                // Should only happen for the Decor
8291                drawingOrderInParent = 0;
8292                break;
8293            } else {
8294                final ViewGroup parentGroup = (ViewGroup) currentParent;
8295                final int childCount = parentGroup.getChildCount();
8296                if (childCount > 1) {
8297                    List<View> preorderedList = parentGroup.buildOrderedChildList();
8298                    if (preorderedList != null) {
8299                        final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel);
8300                        for (int i = 0; i < childDrawIndex; i++) {
8301                            drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i));
8302                        }
8303                    } else {
8304                        final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel);
8305                        final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled();
8306                        final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup
8307                                .getChildDrawingOrder(childCount, childIndex) : childIndex;
8308                        final int numChildrenToIterate = customOrder ? childCount : childDrawIndex;
8309                        if (childDrawIndex != 0) {
8310                            for (int i = 0; i < numChildrenToIterate; i++) {
8311                                final int otherDrawIndex = (customOrder ?
8312                                        parentGroup.getChildDrawingOrder(childCount, i) : i);
8313                                if (otherDrawIndex < childDrawIndex) {
8314                                    drawingOrderInParent +=
8315                                            numViewsForAccessibility(parentGroup.getChildAt(i));
8316                                }
8317                            }
8318                        }
8319                    }
8320                }
8321            }
8322            viewAtDrawingLevel = (View) currentParent;
8323        }
8324        info.setDrawingOrder(drawingOrderInParent);
8325    }
8326
8327    private static int numViewsForAccessibility(View view) {
8328        if (view != null) {
8329            if (view.includeForAccessibility()) {
8330                return 1;
8331            } else if (view instanceof ViewGroup) {
8332                return ((ViewGroup) view).getNumChildrenForAccessibility();
8333            }
8334        }
8335        return 0;
8336    }
8337
8338    private View findLabelForView(View view, int labeledId) {
8339        if (mMatchLabelForPredicate == null) {
8340            mMatchLabelForPredicate = new MatchLabelForPredicate();
8341        }
8342        mMatchLabelForPredicate.mLabeledId = labeledId;
8343        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
8344    }
8345
8346    /**
8347     * Computes whether this view is visible to the user. Such a view is
8348     * attached, visible, all its predecessors are visible, it is not clipped
8349     * entirely by its predecessors, and has an alpha greater than zero.
8350     *
8351     * @return Whether the view is visible on the screen.
8352     *
8353     * @hide
8354     */
8355    protected boolean isVisibleToUser() {
8356        return isVisibleToUser(null);
8357    }
8358
8359    /**
8360     * Computes whether the given portion of this view is visible to the user.
8361     * Such a view is attached, visible, all its predecessors are visible,
8362     * has an alpha greater than zero, and the specified portion is not
8363     * clipped entirely by its predecessors.
8364     *
8365     * @param boundInView the portion of the view to test; coordinates should be relative; may be
8366     *                    <code>null</code>, and the entire view will be tested in this case.
8367     *                    When <code>true</code> is returned by the function, the actual visible
8368     *                    region will be stored in this parameter; that is, if boundInView is fully
8369     *                    contained within the view, no modification will be made, otherwise regions
8370     *                    outside of the visible area of the view will be clipped.
8371     *
8372     * @return Whether the specified portion of the view is visible on the screen.
8373     *
8374     * @hide
8375     */
8376    protected boolean isVisibleToUser(Rect boundInView) {
8377        if (mAttachInfo != null) {
8378            // Attached to invisible window means this view is not visible.
8379            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
8380                return false;
8381            }
8382            // An invisible predecessor or one with alpha zero means
8383            // that this view is not visible to the user.
8384            Object current = this;
8385            while (current instanceof View) {
8386                View view = (View) current;
8387                // We have attach info so this view is attached and there is no
8388                // need to check whether we reach to ViewRootImpl on the way up.
8389                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
8390                        view.getVisibility() != VISIBLE) {
8391                    return false;
8392                }
8393                current = view.mParent;
8394            }
8395            // Check if the view is entirely covered by its predecessors.
8396            Rect visibleRect = mAttachInfo.mTmpInvalRect;
8397            Point offset = mAttachInfo.mPoint;
8398            if (!getGlobalVisibleRect(visibleRect, offset)) {
8399                return false;
8400            }
8401            // Check if the visible portion intersects the rectangle of interest.
8402            if (boundInView != null) {
8403                visibleRect.offset(-offset.x, -offset.y);
8404                return boundInView.intersect(visibleRect);
8405            }
8406            return true;
8407        }
8408        return false;
8409    }
8410
8411    /**
8412     * Returns the delegate for implementing accessibility support via
8413     * composition. For more details see {@link AccessibilityDelegate}.
8414     *
8415     * @return The delegate, or null if none set.
8416     *
8417     * @hide
8418     */
8419    public AccessibilityDelegate getAccessibilityDelegate() {
8420        return mAccessibilityDelegate;
8421    }
8422
8423    /**
8424     * Sets a delegate for implementing accessibility support via composition
8425     * (as opposed to inheritance). For more details, see
8426     * {@link AccessibilityDelegate}.
8427     * <p>
8428     * <strong>Note:</strong> On platform versions prior to
8429     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
8430     * views in the {@code android.widget.*} package are called <i>before</i>
8431     * host methods. This prevents certain properties such as class name from
8432     * being modified by overriding
8433     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
8434     * as any changes will be overwritten by the host class.
8435     * <p>
8436     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
8437     * methods are called <i>after</i> host methods, which all properties to be
8438     * modified without being overwritten by the host class.
8439     *
8440     * @param delegate the object to which accessibility method calls should be
8441     *                 delegated
8442     * @see AccessibilityDelegate
8443     */
8444    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
8445        mAccessibilityDelegate = delegate;
8446    }
8447
8448    /**
8449     * Gets the provider for managing a virtual view hierarchy rooted at this View
8450     * and reported to {@link android.accessibilityservice.AccessibilityService}s
8451     * that explore the window content.
8452     * <p>
8453     * If this method returns an instance, this instance is responsible for managing
8454     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
8455     * View including the one representing the View itself. Similarly the returned
8456     * instance is responsible for performing accessibility actions on any virtual
8457     * view or the root view itself.
8458     * </p>
8459     * <p>
8460     * If an {@link AccessibilityDelegate} has been specified via calling
8461     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8462     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
8463     * is responsible for handling this call.
8464     * </p>
8465     *
8466     * @return The provider.
8467     *
8468     * @see AccessibilityNodeProvider
8469     */
8470    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
8471        if (mAccessibilityDelegate != null) {
8472            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
8473        } else {
8474            return null;
8475        }
8476    }
8477
8478    /**
8479     * Gets the unique identifier of this view on the screen for accessibility purposes.
8480     *
8481     * @return The view accessibility id.
8482     *
8483     * @hide
8484     */
8485    public int getAccessibilityViewId() {
8486        if (mAccessibilityViewId == NO_ID) {
8487            mAccessibilityViewId = sNextAccessibilityViewId++;
8488        }
8489        return mAccessibilityViewId;
8490    }
8491
8492    /**
8493     * Gets the unique identifier of this view on the screen for autofill purposes.
8494     *
8495     * @return The view autofill id.
8496     *
8497     * @hide
8498     */
8499    public int getAutofillViewId() {
8500        if (mAutofillViewId == NO_ID) {
8501            mAutofillViewId = mContext.getNextAutofillId();
8502        }
8503        return mAutofillViewId;
8504    }
8505
8506    /**
8507     * Gets the unique identifier of the window in which this View reseides.
8508     *
8509     * @return The window accessibility id.
8510     *
8511     * @hide
8512     */
8513    public int getAccessibilityWindowId() {
8514        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
8515                : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
8516    }
8517
8518    /**
8519     * Returns the {@link View}'s content description.
8520     * <p>
8521     * <strong>Note:</strong> Do not override this method, as it will have no
8522     * effect on the content description presented to accessibility services.
8523     * You must call {@link #setContentDescription(CharSequence)} to modify the
8524     * content description.
8525     *
8526     * @return the content description
8527     * @see #setContentDescription(CharSequence)
8528     * @attr ref android.R.styleable#View_contentDescription
8529     */
8530    @ViewDebug.ExportedProperty(category = "accessibility")
8531    public CharSequence getContentDescription() {
8532        return mContentDescription;
8533    }
8534
8535    /**
8536     * Sets the {@link View}'s content description.
8537     * <p>
8538     * A content description briefly describes the view and is primarily used
8539     * for accessibility support to determine how a view should be presented to
8540     * the user. In the case of a view with no textual representation, such as
8541     * {@link android.widget.ImageButton}, a useful content description
8542     * explains what the view does. For example, an image button with a phone
8543     * icon that is used to place a call may use "Call" as its content
8544     * description. An image of a floppy disk that is used to save a file may
8545     * use "Save".
8546     *
8547     * @param contentDescription The content description.
8548     * @see #getContentDescription()
8549     * @attr ref android.R.styleable#View_contentDescription
8550     */
8551    @RemotableViewMethod
8552    public void setContentDescription(CharSequence contentDescription) {
8553        if (mContentDescription == null) {
8554            if (contentDescription == null) {
8555                return;
8556            }
8557        } else if (mContentDescription.equals(contentDescription)) {
8558            return;
8559        }
8560        mContentDescription = contentDescription;
8561        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
8562        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
8563            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
8564            notifySubtreeAccessibilityStateChangedIfNeeded();
8565        } else {
8566            notifyViewAccessibilityStateChangedIfNeeded(
8567                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
8568        }
8569    }
8570
8571    /**
8572     * Sets the id of a view before which this one is visited in accessibility traversal.
8573     * A screen-reader must visit the content of this view before the content of the one
8574     * it precedes. For example, if view B is set to be before view A, then a screen-reader
8575     * will traverse the entire content of B before traversing the entire content of A,
8576     * regardles of what traversal strategy it is using.
8577     * <p>
8578     * Views that do not have specified before/after relationships are traversed in order
8579     * determined by the screen-reader.
8580     * </p>
8581     * <p>
8582     * Setting that this view is before a view that is not important for accessibility
8583     * or if this view is not important for accessibility will have no effect as the
8584     * screen-reader is not aware of unimportant views.
8585     * </p>
8586     *
8587     * @param beforeId The id of a view this one precedes in accessibility traversal.
8588     *
8589     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
8590     *
8591     * @see #setImportantForAccessibility(int)
8592     */
8593    @RemotableViewMethod
8594    public void setAccessibilityTraversalBefore(int beforeId) {
8595        if (mAccessibilityTraversalBeforeId == beforeId) {
8596            return;
8597        }
8598        mAccessibilityTraversalBeforeId = beforeId;
8599        notifyViewAccessibilityStateChangedIfNeeded(
8600                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8601    }
8602
8603    /**
8604     * Gets the id of a view before which this one is visited in accessibility traversal.
8605     *
8606     * @return The id of a view this one precedes in accessibility traversal if
8607     *         specified, otherwise {@link #NO_ID}.
8608     *
8609     * @see #setAccessibilityTraversalBefore(int)
8610     */
8611    public int getAccessibilityTraversalBefore() {
8612        return mAccessibilityTraversalBeforeId;
8613    }
8614
8615    /**
8616     * Sets the id of a view after which this one is visited in accessibility traversal.
8617     * A screen-reader must visit the content of the other view before the content of this
8618     * one. For example, if view B is set to be after view A, then a screen-reader
8619     * will traverse the entire content of A before traversing the entire content of B,
8620     * regardles of what traversal strategy it is using.
8621     * <p>
8622     * Views that do not have specified before/after relationships are traversed in order
8623     * determined by the screen-reader.
8624     * </p>
8625     * <p>
8626     * Setting that this view is after a view that is not important for accessibility
8627     * or if this view is not important for accessibility will have no effect as the
8628     * screen-reader is not aware of unimportant views.
8629     * </p>
8630     *
8631     * @param afterId The id of a view this one succedees in accessibility traversal.
8632     *
8633     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
8634     *
8635     * @see #setImportantForAccessibility(int)
8636     */
8637    @RemotableViewMethod
8638    public void setAccessibilityTraversalAfter(int afterId) {
8639        if (mAccessibilityTraversalAfterId == afterId) {
8640            return;
8641        }
8642        mAccessibilityTraversalAfterId = afterId;
8643        notifyViewAccessibilityStateChangedIfNeeded(
8644                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8645    }
8646
8647    /**
8648     * Gets the id of a view after which this one is visited in accessibility traversal.
8649     *
8650     * @return The id of a view this one succeedes in accessibility traversal if
8651     *         specified, otherwise {@link #NO_ID}.
8652     *
8653     * @see #setAccessibilityTraversalAfter(int)
8654     */
8655    public int getAccessibilityTraversalAfter() {
8656        return mAccessibilityTraversalAfterId;
8657    }
8658
8659    /**
8660     * Gets the id of a view for which this view serves as a label for
8661     * accessibility purposes.
8662     *
8663     * @return The labeled view id.
8664     */
8665    @ViewDebug.ExportedProperty(category = "accessibility")
8666    public int getLabelFor() {
8667        return mLabelForId;
8668    }
8669
8670    /**
8671     * Sets the id of a view for which this view serves as a label for
8672     * accessibility purposes.
8673     *
8674     * @param id The labeled view id.
8675     */
8676    @RemotableViewMethod
8677    public void setLabelFor(@IdRes int id) {
8678        if (mLabelForId == id) {
8679            return;
8680        }
8681        mLabelForId = id;
8682        if (mLabelForId != View.NO_ID
8683                && mID == View.NO_ID) {
8684            mID = generateViewId();
8685        }
8686        notifyViewAccessibilityStateChangedIfNeeded(
8687                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8688    }
8689
8690    /**
8691     * Invoked whenever this view loses focus, either by losing window focus or by losing
8692     * focus within its window. This method can be used to clear any state tied to the
8693     * focus. For instance, if a button is held pressed with the trackball and the window
8694     * loses focus, this method can be used to cancel the press.
8695     *
8696     * Subclasses of View overriding this method should always call super.onFocusLost().
8697     *
8698     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
8699     * @see #onWindowFocusChanged(boolean)
8700     *
8701     * @hide pending API council approval
8702     */
8703    @CallSuper
8704    protected void onFocusLost() {
8705        resetPressedState();
8706    }
8707
8708    private void resetPressedState() {
8709        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8710            return;
8711        }
8712
8713        if (isPressed()) {
8714            setPressed(false);
8715
8716            if (!mHasPerformedLongPress) {
8717                removeLongPressCallback();
8718            }
8719        }
8720    }
8721
8722    /**
8723     * Returns true if this view has focus
8724     *
8725     * @return True if this view has focus, false otherwise.
8726     */
8727    @ViewDebug.ExportedProperty(category = "focus")
8728    public boolean isFocused() {
8729        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
8730    }
8731
8732    /**
8733     * Find the view in the hierarchy rooted at this view that currently has
8734     * focus.
8735     *
8736     * @return The view that currently has focus, or null if no focused view can
8737     *         be found.
8738     */
8739    public View findFocus() {
8740        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
8741    }
8742
8743    /**
8744     * Indicates whether this view is one of the set of scrollable containers in
8745     * its window.
8746     *
8747     * @return whether this view is one of the set of scrollable containers in
8748     * its window
8749     *
8750     * @attr ref android.R.styleable#View_isScrollContainer
8751     */
8752    public boolean isScrollContainer() {
8753        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
8754    }
8755
8756    /**
8757     * Change whether this view is one of the set of scrollable containers in
8758     * its window.  This will be used to determine whether the window can
8759     * resize or must pan when a soft input area is open -- scrollable
8760     * containers allow the window to use resize mode since the container
8761     * will appropriately shrink.
8762     *
8763     * @attr ref android.R.styleable#View_isScrollContainer
8764     */
8765    public void setScrollContainer(boolean isScrollContainer) {
8766        if (isScrollContainer) {
8767            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
8768                mAttachInfo.mScrollContainers.add(this);
8769                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
8770            }
8771            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
8772        } else {
8773            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
8774                mAttachInfo.mScrollContainers.remove(this);
8775            }
8776            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
8777        }
8778    }
8779
8780    /**
8781     * Returns the quality of the drawing cache.
8782     *
8783     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8784     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8785     *
8786     * @see #setDrawingCacheQuality(int)
8787     * @see #setDrawingCacheEnabled(boolean)
8788     * @see #isDrawingCacheEnabled()
8789     *
8790     * @attr ref android.R.styleable#View_drawingCacheQuality
8791     */
8792    @DrawingCacheQuality
8793    public int getDrawingCacheQuality() {
8794        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
8795    }
8796
8797    /**
8798     * Set the drawing cache quality of this view. This value is used only when the
8799     * drawing cache is enabled
8800     *
8801     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
8802     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
8803     *
8804     * @see #getDrawingCacheQuality()
8805     * @see #setDrawingCacheEnabled(boolean)
8806     * @see #isDrawingCacheEnabled()
8807     *
8808     * @attr ref android.R.styleable#View_drawingCacheQuality
8809     */
8810    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
8811        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
8812    }
8813
8814    /**
8815     * Returns whether the screen should remain on, corresponding to the current
8816     * value of {@link #KEEP_SCREEN_ON}.
8817     *
8818     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
8819     *
8820     * @see #setKeepScreenOn(boolean)
8821     *
8822     * @attr ref android.R.styleable#View_keepScreenOn
8823     */
8824    public boolean getKeepScreenOn() {
8825        return (mViewFlags & KEEP_SCREEN_ON) != 0;
8826    }
8827
8828    /**
8829     * Controls whether the screen should remain on, modifying the
8830     * value of {@link #KEEP_SCREEN_ON}.
8831     *
8832     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
8833     *
8834     * @see #getKeepScreenOn()
8835     *
8836     * @attr ref android.R.styleable#View_keepScreenOn
8837     */
8838    public void setKeepScreenOn(boolean keepScreenOn) {
8839        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
8840    }
8841
8842    /**
8843     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8844     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8845     *
8846     * @attr ref android.R.styleable#View_nextFocusLeft
8847     */
8848    public int getNextFocusLeftId() {
8849        return mNextFocusLeftId;
8850    }
8851
8852    /**
8853     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
8854     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
8855     * decide automatically.
8856     *
8857     * @attr ref android.R.styleable#View_nextFocusLeft
8858     */
8859    public void setNextFocusLeftId(int nextFocusLeftId) {
8860        mNextFocusLeftId = nextFocusLeftId;
8861    }
8862
8863    /**
8864     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8865     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8866     *
8867     * @attr ref android.R.styleable#View_nextFocusRight
8868     */
8869    public int getNextFocusRightId() {
8870        return mNextFocusRightId;
8871    }
8872
8873    /**
8874     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
8875     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
8876     * decide automatically.
8877     *
8878     * @attr ref android.R.styleable#View_nextFocusRight
8879     */
8880    public void setNextFocusRightId(int nextFocusRightId) {
8881        mNextFocusRightId = nextFocusRightId;
8882    }
8883
8884    /**
8885     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8886     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8887     *
8888     * @attr ref android.R.styleable#View_nextFocusUp
8889     */
8890    public int getNextFocusUpId() {
8891        return mNextFocusUpId;
8892    }
8893
8894    /**
8895     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
8896     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
8897     * decide automatically.
8898     *
8899     * @attr ref android.R.styleable#View_nextFocusUp
8900     */
8901    public void setNextFocusUpId(int nextFocusUpId) {
8902        mNextFocusUpId = nextFocusUpId;
8903    }
8904
8905    /**
8906     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8907     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8908     *
8909     * @attr ref android.R.styleable#View_nextFocusDown
8910     */
8911    public int getNextFocusDownId() {
8912        return mNextFocusDownId;
8913    }
8914
8915    /**
8916     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
8917     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
8918     * decide automatically.
8919     *
8920     * @attr ref android.R.styleable#View_nextFocusDown
8921     */
8922    public void setNextFocusDownId(int nextFocusDownId) {
8923        mNextFocusDownId = nextFocusDownId;
8924    }
8925
8926    /**
8927     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8928     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
8929     *
8930     * @attr ref android.R.styleable#View_nextFocusForward
8931     */
8932    public int getNextFocusForwardId() {
8933        return mNextFocusForwardId;
8934    }
8935
8936    /**
8937     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
8938     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
8939     * decide automatically.
8940     *
8941     * @attr ref android.R.styleable#View_nextFocusForward
8942     */
8943    public void setNextFocusForwardId(int nextFocusForwardId) {
8944        mNextFocusForwardId = nextFocusForwardId;
8945    }
8946
8947    /**
8948     * Gets the id of the root of the next keyboard navigation cluster.
8949     * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should
8950     * decide automatically.
8951     *
8952     * @attr ref android.R.styleable#View_nextClusterForward
8953     */
8954    public int getNextClusterForwardId() {
8955        return mNextClusterForwardId;
8956    }
8957
8958    /**
8959     * Sets the id of the view to use as the root of the next keyboard navigation cluster.
8960     * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should
8961     * decide automatically.
8962     *
8963     * @attr ref android.R.styleable#View_nextClusterForward
8964     */
8965    public void setNextClusterForwardId(int nextClusterForwardId) {
8966        mNextClusterForwardId = nextClusterForwardId;
8967    }
8968
8969    /**
8970     * Returns the visibility of this view and all of its ancestors
8971     *
8972     * @return True if this view and all of its ancestors are {@link #VISIBLE}
8973     */
8974    public boolean isShown() {
8975        View current = this;
8976        //noinspection ConstantConditions
8977        do {
8978            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8979                return false;
8980            }
8981            ViewParent parent = current.mParent;
8982            if (parent == null) {
8983                return false; // We are not attached to the view root
8984            }
8985            if (!(parent instanceof View)) {
8986                return true;
8987            }
8988            current = (View) parent;
8989        } while (current != null);
8990
8991        return false;
8992    }
8993
8994    /**
8995     * Called by the view hierarchy when the content insets for a window have
8996     * changed, to allow it to adjust its content to fit within those windows.
8997     * The content insets tell you the space that the status bar, input method,
8998     * and other system windows infringe on the application's window.
8999     *
9000     * <p>You do not normally need to deal with this function, since the default
9001     * window decoration given to applications takes care of applying it to the
9002     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
9003     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
9004     * and your content can be placed under those system elements.  You can then
9005     * use this method within your view hierarchy if you have parts of your UI
9006     * which you would like to ensure are not being covered.
9007     *
9008     * <p>The default implementation of this method simply applies the content
9009     * insets to the view's padding, consuming that content (modifying the
9010     * insets to be 0), and returning true.  This behavior is off by default, but can
9011     * be enabled through {@link #setFitsSystemWindows(boolean)}.
9012     *
9013     * <p>This function's traversal down the hierarchy is depth-first.  The same content
9014     * insets object is propagated down the hierarchy, so any changes made to it will
9015     * be seen by all following views (including potentially ones above in
9016     * the hierarchy since this is a depth-first traversal).  The first view
9017     * that returns true will abort the entire traversal.
9018     *
9019     * <p>The default implementation works well for a situation where it is
9020     * used with a container that covers the entire window, allowing it to
9021     * apply the appropriate insets to its content on all edges.  If you need
9022     * a more complicated layout (such as two different views fitting system
9023     * windows, one on the top of the window, and one on the bottom),
9024     * you can override the method and handle the insets however you would like.
9025     * Note that the insets provided by the framework are always relative to the
9026     * far edges of the window, not accounting for the location of the called view
9027     * within that window.  (In fact when this method is called you do not yet know
9028     * where the layout will place the view, as it is done before layout happens.)
9029     *
9030     * <p>Note: unlike many View methods, there is no dispatch phase to this
9031     * call.  If you are overriding it in a ViewGroup and want to allow the
9032     * call to continue to your children, you must be sure to call the super
9033     * implementation.
9034     *
9035     * <p>Here is a sample layout that makes use of fitting system windows
9036     * to have controls for a video view placed inside of the window decorations
9037     * that it hides and shows.  This can be used with code like the second
9038     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
9039     *
9040     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
9041     *
9042     * @param insets Current content insets of the window.  Prior to
9043     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
9044     * the insets or else you and Android will be unhappy.
9045     *
9046     * @return {@code true} if this view applied the insets and it should not
9047     * continue propagating further down the hierarchy, {@code false} otherwise.
9048     * @see #getFitsSystemWindows()
9049     * @see #setFitsSystemWindows(boolean)
9050     * @see #setSystemUiVisibility(int)
9051     *
9052     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
9053     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
9054     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
9055     * to implement handling their own insets.
9056     */
9057    @Deprecated
9058    protected boolean fitSystemWindows(Rect insets) {
9059        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
9060            if (insets == null) {
9061                // Null insets by definition have already been consumed.
9062                // This call cannot apply insets since there are none to apply,
9063                // so return false.
9064                return false;
9065            }
9066            // If we're not in the process of dispatching the newer apply insets call,
9067            // that means we're not in the compatibility path. Dispatch into the newer
9068            // apply insets path and take things from there.
9069            try {
9070                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
9071                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
9072            } finally {
9073                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
9074            }
9075        } else {
9076            // We're being called from the newer apply insets path.
9077            // Perform the standard fallback behavior.
9078            return fitSystemWindowsInt(insets);
9079        }
9080    }
9081
9082    private boolean fitSystemWindowsInt(Rect insets) {
9083        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
9084            mUserPaddingStart = UNDEFINED_PADDING;
9085            mUserPaddingEnd = UNDEFINED_PADDING;
9086            Rect localInsets = sThreadLocal.get();
9087            if (localInsets == null) {
9088                localInsets = new Rect();
9089                sThreadLocal.set(localInsets);
9090            }
9091            boolean res = computeFitSystemWindows(insets, localInsets);
9092            mUserPaddingLeftInitial = localInsets.left;
9093            mUserPaddingRightInitial = localInsets.right;
9094            internalSetPadding(localInsets.left, localInsets.top,
9095                    localInsets.right, localInsets.bottom);
9096            return res;
9097        }
9098        return false;
9099    }
9100
9101    /**
9102     * Called when the view should apply {@link WindowInsets} according to its internal policy.
9103     *
9104     * <p>This method should be overridden by views that wish to apply a policy different from or
9105     * in addition to the default behavior. Clients that wish to force a view subtree
9106     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
9107     *
9108     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
9109     * it will be called during dispatch instead of this method. The listener may optionally
9110     * call this method from its own implementation if it wishes to apply the view's default
9111     * insets policy in addition to its own.</p>
9112     *
9113     * <p>Implementations of this method should either return the insets parameter unchanged
9114     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
9115     * that this view applied itself. This allows new inset types added in future platform
9116     * versions to pass through existing implementations unchanged without being erroneously
9117     * consumed.</p>
9118     *
9119     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
9120     * property is set then the view will consume the system window insets and apply them
9121     * as padding for the view.</p>
9122     *
9123     * @param insets Insets to apply
9124     * @return The supplied insets with any applied insets consumed
9125     */
9126    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
9127        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
9128            // We weren't called from within a direct call to fitSystemWindows,
9129            // call into it as a fallback in case we're in a class that overrides it
9130            // and has logic to perform.
9131            if (fitSystemWindows(insets.getSystemWindowInsets())) {
9132                return insets.consumeSystemWindowInsets();
9133            }
9134        } else {
9135            // We were called from within a direct call to fitSystemWindows.
9136            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
9137                return insets.consumeSystemWindowInsets();
9138            }
9139        }
9140        return insets;
9141    }
9142
9143    /**
9144     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
9145     * window insets to this view. The listener's
9146     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
9147     * method will be called instead of the view's
9148     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
9149     *
9150     * @param listener Listener to set
9151     *
9152     * @see #onApplyWindowInsets(WindowInsets)
9153     */
9154    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
9155        getListenerInfo().mOnApplyWindowInsetsListener = listener;
9156    }
9157
9158    /**
9159     * Request to apply the given window insets to this view or another view in its subtree.
9160     *
9161     * <p>This method should be called by clients wishing to apply insets corresponding to areas
9162     * obscured by window decorations or overlays. This can include the status and navigation bars,
9163     * action bars, input methods and more. New inset categories may be added in the future.
9164     * The method returns the insets provided minus any that were applied by this view or its
9165     * children.</p>
9166     *
9167     * <p>Clients wishing to provide custom behavior should override the
9168     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
9169     * {@link OnApplyWindowInsetsListener} via the
9170     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
9171     * method.</p>
9172     *
9173     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
9174     * </p>
9175     *
9176     * @param insets Insets to apply
9177     * @return The provided insets minus the insets that were consumed
9178     */
9179    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
9180        try {
9181            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
9182            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
9183                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
9184            } else {
9185                return onApplyWindowInsets(insets);
9186            }
9187        } finally {
9188            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
9189        }
9190    }
9191
9192    /**
9193     * Compute the view's coordinate within the surface.
9194     *
9195     * <p>Computes the coordinates of this view in its surface. The argument
9196     * must be an array of two integers. After the method returns, the array
9197     * contains the x and y location in that order.</p>
9198     * @hide
9199     * @param location an array of two integers in which to hold the coordinates
9200     */
9201    public void getLocationInSurface(@Size(2) int[] location) {
9202        getLocationInWindow(location);
9203        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
9204            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
9205            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
9206        }
9207    }
9208
9209    /**
9210     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
9211     * only available if the view is attached.
9212     *
9213     * @return WindowInsets from the top of the view hierarchy or null if View is detached
9214     */
9215    public WindowInsets getRootWindowInsets() {
9216        if (mAttachInfo != null) {
9217            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
9218        }
9219        return null;
9220    }
9221
9222    /**
9223     * @hide Compute the insets that should be consumed by this view and the ones
9224     * that should propagate to those under it.
9225     */
9226    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
9227        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9228                || mAttachInfo == null
9229                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
9230                        && !mAttachInfo.mOverscanRequested)) {
9231            outLocalInsets.set(inoutInsets);
9232            inoutInsets.set(0, 0, 0, 0);
9233            return true;
9234        } else {
9235            // The application wants to take care of fitting system window for
9236            // the content...  however we still need to take care of any overscan here.
9237            final Rect overscan = mAttachInfo.mOverscanInsets;
9238            outLocalInsets.set(overscan);
9239            inoutInsets.left -= overscan.left;
9240            inoutInsets.top -= overscan.top;
9241            inoutInsets.right -= overscan.right;
9242            inoutInsets.bottom -= overscan.bottom;
9243            return false;
9244        }
9245    }
9246
9247    /**
9248     * Compute insets that should be consumed by this view and the ones that should propagate
9249     * to those under it.
9250     *
9251     * @param in Insets currently being processed by this View, likely received as a parameter
9252     *           to {@link #onApplyWindowInsets(WindowInsets)}.
9253     * @param outLocalInsets A Rect that will receive the insets that should be consumed
9254     *                       by this view
9255     * @return Insets that should be passed along to views under this one
9256     */
9257    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
9258        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
9259                || mAttachInfo == null
9260                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
9261            outLocalInsets.set(in.getSystemWindowInsets());
9262            return in.consumeSystemWindowInsets();
9263        } else {
9264            outLocalInsets.set(0, 0, 0, 0);
9265            return in;
9266        }
9267    }
9268
9269    /**
9270     * Sets whether or not this view should account for system screen decorations
9271     * such as the status bar and inset its content; that is, controlling whether
9272     * the default implementation of {@link #fitSystemWindows(Rect)} will be
9273     * executed.  See that method for more details.
9274     *
9275     * <p>Note that if you are providing your own implementation of
9276     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
9277     * flag to true -- your implementation will be overriding the default
9278     * implementation that checks this flag.
9279     *
9280     * @param fitSystemWindows If true, then the default implementation of
9281     * {@link #fitSystemWindows(Rect)} will be executed.
9282     *
9283     * @attr ref android.R.styleable#View_fitsSystemWindows
9284     * @see #getFitsSystemWindows()
9285     * @see #fitSystemWindows(Rect)
9286     * @see #setSystemUiVisibility(int)
9287     */
9288    public void setFitsSystemWindows(boolean fitSystemWindows) {
9289        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
9290    }
9291
9292    /**
9293     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
9294     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
9295     * will be executed.
9296     *
9297     * @return {@code true} if the default implementation of
9298     * {@link #fitSystemWindows(Rect)} will be executed.
9299     *
9300     * @attr ref android.R.styleable#View_fitsSystemWindows
9301     * @see #setFitsSystemWindows(boolean)
9302     * @see #fitSystemWindows(Rect)
9303     * @see #setSystemUiVisibility(int)
9304     */
9305    @ViewDebug.ExportedProperty
9306    public boolean getFitsSystemWindows() {
9307        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
9308    }
9309
9310    /** @hide */
9311    public boolean fitsSystemWindows() {
9312        return getFitsSystemWindows();
9313    }
9314
9315    /**
9316     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
9317     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
9318     */
9319    @Deprecated
9320    public void requestFitSystemWindows() {
9321        if (mParent != null) {
9322            mParent.requestFitSystemWindows();
9323        }
9324    }
9325
9326    /**
9327     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
9328     */
9329    public void requestApplyInsets() {
9330        requestFitSystemWindows();
9331    }
9332
9333    /**
9334     * For use by PhoneWindow to make its own system window fitting optional.
9335     * @hide
9336     */
9337    public void makeOptionalFitsSystemWindows() {
9338        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
9339    }
9340
9341    /**
9342     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
9343     * treat them as such.
9344     * @hide
9345     */
9346    public void getOutsets(Rect outOutsetRect) {
9347        if (mAttachInfo != null) {
9348            outOutsetRect.set(mAttachInfo.mOutsets);
9349        } else {
9350            outOutsetRect.setEmpty();
9351        }
9352    }
9353
9354    /**
9355     * Returns the visibility status for this view.
9356     *
9357     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9358     * @attr ref android.R.styleable#View_visibility
9359     */
9360    @ViewDebug.ExportedProperty(mapping = {
9361        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
9362        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
9363        @ViewDebug.IntToString(from = GONE,      to = "GONE")
9364    })
9365    @Visibility
9366    public int getVisibility() {
9367        return mViewFlags & VISIBILITY_MASK;
9368    }
9369
9370    /**
9371     * Set the visibility state of this view.
9372     *
9373     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9374     * @attr ref android.R.styleable#View_visibility
9375     */
9376    @RemotableViewMethod
9377    public void setVisibility(@Visibility int visibility) {
9378        setFlags(visibility, VISIBILITY_MASK);
9379    }
9380
9381    /**
9382     * Returns the enabled status for this view. The interpretation of the
9383     * enabled state varies by subclass.
9384     *
9385     * @return True if this view is enabled, false otherwise.
9386     */
9387    @ViewDebug.ExportedProperty
9388    public boolean isEnabled() {
9389        return (mViewFlags & ENABLED_MASK) == ENABLED;
9390    }
9391
9392    /**
9393     * Set the enabled state of this view. The interpretation of the enabled
9394     * state varies by subclass.
9395     *
9396     * @param enabled True if this view is enabled, false otherwise.
9397     */
9398    @RemotableViewMethod
9399    public void setEnabled(boolean enabled) {
9400        if (enabled == isEnabled()) return;
9401
9402        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
9403
9404        /*
9405         * The View most likely has to change its appearance, so refresh
9406         * the drawable state.
9407         */
9408        refreshDrawableState();
9409
9410        // Invalidate too, since the default behavior for views is to be
9411        // be drawn at 50% alpha rather than to change the drawable.
9412        invalidate(true);
9413
9414        if (!enabled) {
9415            cancelPendingInputEvents();
9416        }
9417    }
9418
9419    /**
9420     * Set whether this view can receive the focus.
9421     * <p>
9422     * Setting this to false will also ensure that this view is not focusable
9423     * in touch mode.
9424     *
9425     * @param focusable If true, this view can receive the focus.
9426     *
9427     * @see #setFocusableInTouchMode(boolean)
9428     * @see #setFocusable(int)
9429     * @attr ref android.R.styleable#View_focusable
9430     */
9431    public void setFocusable(boolean focusable) {
9432        setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE);
9433    }
9434
9435    /**
9436     * Sets whether this view can receive focus.
9437     * <p>
9438     * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability
9439     * automatically based on the view's interactivity. This is the default.
9440     * <p>
9441     * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable
9442     * in touch mode.
9443     *
9444     * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE},
9445     *                  or {@link #FOCUSABLE_AUTO}.
9446     * @see #setFocusableInTouchMode(boolean)
9447     * @attr ref android.R.styleable#View_focusable
9448     */
9449    public void setFocusable(@Focusable int focusable) {
9450        if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) {
9451            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
9452        }
9453        setFlags(focusable, FOCUSABLE_MASK);
9454    }
9455
9456    /**
9457     * Set whether this view can receive focus while in touch mode.
9458     *
9459     * Setting this to true will also ensure that this view is focusable.
9460     *
9461     * @param focusableInTouchMode If true, this view can receive the focus while
9462     *   in touch mode.
9463     *
9464     * @see #setFocusable(boolean)
9465     * @attr ref android.R.styleable#View_focusableInTouchMode
9466     */
9467    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
9468        // Focusable in touch mode should always be set before the focusable flag
9469        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
9470        // which, in touch mode, will not successfully request focus on this view
9471        // because the focusable in touch mode flag is not set
9472        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
9473
9474        // Clear FOCUSABLE_AUTO if set.
9475        if (focusableInTouchMode) {
9476            // Clears FOCUSABLE_AUTO if set.
9477            setFlags(FOCUSABLE, FOCUSABLE_MASK);
9478        }
9479    }
9480
9481    /**
9482     * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
9483     * to autofill the view with the user's data.
9484     *
9485     * <p>Typically, there is only one way to autofill a view, but there could be more than one.
9486     * For example, if the application accepts either an username or email address to identify
9487     * an user.
9488     *
9489     * <p>These hints are not validated by the Android System, but passed "as is" to the service.
9490     * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
9491     * constants such as:
9492     * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
9493     * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
9494     * {@link #AUTOFILL_HINT_NAME},
9495     * {@link #AUTOFILL_HINT_PHONE},
9496     * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
9497     * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
9498     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
9499     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
9500     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
9501     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
9502     *
9503     * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
9504     * @attr ref android.R.styleable#View_autofillHints
9505     */
9506    public void setAutofillHints(@Nullable String... autofillHints) {
9507        if (autofillHints == null || autofillHints.length == 0) {
9508            mAutofillHints = null;
9509        } else {
9510            mAutofillHints = autofillHints;
9511        }
9512    }
9513
9514    /**
9515     * @hide
9516     */
9517    @TestApi
9518    public void setAutofilled(boolean isAutofilled) {
9519        boolean wasChanged = isAutofilled != isAutofilled();
9520
9521        if (wasChanged) {
9522            if (isAutofilled) {
9523                mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED;
9524            } else {
9525                mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED;
9526            }
9527
9528            invalidate();
9529        }
9530    }
9531
9532    /**
9533     * Set whether this view should have sound effects enabled for events such as
9534     * clicking and touching.
9535     *
9536     * <p>You may wish to disable sound effects for a view if you already play sounds,
9537     * for instance, a dial key that plays dtmf tones.
9538     *
9539     * @param soundEffectsEnabled whether sound effects are enabled for this view.
9540     * @see #isSoundEffectsEnabled()
9541     * @see #playSoundEffect(int)
9542     * @attr ref android.R.styleable#View_soundEffectsEnabled
9543     */
9544    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
9545        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
9546    }
9547
9548    /**
9549     * @return whether this view should have sound effects enabled for events such as
9550     *     clicking and touching.
9551     *
9552     * @see #setSoundEffectsEnabled(boolean)
9553     * @see #playSoundEffect(int)
9554     * @attr ref android.R.styleable#View_soundEffectsEnabled
9555     */
9556    @ViewDebug.ExportedProperty
9557    public boolean isSoundEffectsEnabled() {
9558        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
9559    }
9560
9561    /**
9562     * Set whether this view should have haptic feedback for events such as
9563     * long presses.
9564     *
9565     * <p>You may wish to disable haptic feedback if your view already controls
9566     * its own haptic feedback.
9567     *
9568     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
9569     * @see #isHapticFeedbackEnabled()
9570     * @see #performHapticFeedback(int)
9571     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9572     */
9573    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
9574        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
9575    }
9576
9577    /**
9578     * @return whether this view should have haptic feedback enabled for events
9579     * long presses.
9580     *
9581     * @see #setHapticFeedbackEnabled(boolean)
9582     * @see #performHapticFeedback(int)
9583     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
9584     */
9585    @ViewDebug.ExportedProperty
9586    public boolean isHapticFeedbackEnabled() {
9587        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
9588    }
9589
9590    /**
9591     * Returns the layout direction for this view.
9592     *
9593     * @return One of {@link #LAYOUT_DIRECTION_LTR},
9594     *   {@link #LAYOUT_DIRECTION_RTL},
9595     *   {@link #LAYOUT_DIRECTION_INHERIT} or
9596     *   {@link #LAYOUT_DIRECTION_LOCALE}.
9597     *
9598     * @attr ref android.R.styleable#View_layoutDirection
9599     *
9600     * @hide
9601     */
9602    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9603        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
9604        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
9605        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
9606        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
9607    })
9608    @LayoutDir
9609    public int getRawLayoutDirection() {
9610        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
9611    }
9612
9613    /**
9614     * Set the layout direction for this view. This will propagate a reset of layout direction
9615     * resolution to the view's children and resolve layout direction for this view.
9616     *
9617     * @param layoutDirection the layout direction to set. Should be one of:
9618     *
9619     * {@link #LAYOUT_DIRECTION_LTR},
9620     * {@link #LAYOUT_DIRECTION_RTL},
9621     * {@link #LAYOUT_DIRECTION_INHERIT},
9622     * {@link #LAYOUT_DIRECTION_LOCALE}.
9623     *
9624     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
9625     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
9626     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
9627     *
9628     * @attr ref android.R.styleable#View_layoutDirection
9629     */
9630    @RemotableViewMethod
9631    public void setLayoutDirection(@LayoutDir int layoutDirection) {
9632        if (getRawLayoutDirection() != layoutDirection) {
9633            // Reset the current layout direction and the resolved one
9634            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
9635            resetRtlProperties();
9636            // Set the new layout direction (filtered)
9637            mPrivateFlags2 |=
9638                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
9639            // We need to resolve all RTL properties as they all depend on layout direction
9640            resolveRtlPropertiesIfNeeded();
9641            requestLayout();
9642            invalidate(true);
9643        }
9644    }
9645
9646    /**
9647     * Returns the resolved layout direction for this view.
9648     *
9649     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
9650     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
9651     *
9652     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
9653     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
9654     *
9655     * @attr ref android.R.styleable#View_layoutDirection
9656     */
9657    @ViewDebug.ExportedProperty(category = "layout", mapping = {
9658        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
9659        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
9660    })
9661    @ResolvedLayoutDir
9662    public int getLayoutDirection() {
9663        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
9664        if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
9665            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
9666            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
9667        }
9668        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
9669                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
9670    }
9671
9672    /**
9673     * Indicates whether or not this view's layout is right-to-left. This is resolved from
9674     * layout attribute and/or the inherited value from the parent
9675     *
9676     * @return true if the layout is right-to-left.
9677     *
9678     * @hide
9679     */
9680    @ViewDebug.ExportedProperty(category = "layout")
9681    public boolean isLayoutRtl() {
9682        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
9683    }
9684
9685    /**
9686     * Indicates whether the view is currently tracking transient state that the
9687     * app should not need to concern itself with saving and restoring, but that
9688     * the framework should take special note to preserve when possible.
9689     *
9690     * <p>A view with transient state cannot be trivially rebound from an external
9691     * data source, such as an adapter binding item views in a list. This may be
9692     * because the view is performing an animation, tracking user selection
9693     * of content, or similar.</p>
9694     *
9695     * @return true if the view has transient state
9696     */
9697    @ViewDebug.ExportedProperty(category = "layout")
9698    public boolean hasTransientState() {
9699        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
9700    }
9701
9702    /**
9703     * Set whether this view is currently tracking transient state that the
9704     * framework should attempt to preserve when possible. This flag is reference counted,
9705     * so every call to setHasTransientState(true) should be paired with a later call
9706     * to setHasTransientState(false).
9707     *
9708     * <p>A view with transient state cannot be trivially rebound from an external
9709     * data source, such as an adapter binding item views in a list. This may be
9710     * because the view is performing an animation, tracking user selection
9711     * of content, or similar.</p>
9712     *
9713     * @param hasTransientState true if this view has transient state
9714     */
9715    public void setHasTransientState(boolean hasTransientState) {
9716        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
9717                mTransientStateCount - 1;
9718        if (mTransientStateCount < 0) {
9719            mTransientStateCount = 0;
9720            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
9721                    "unmatched pair of setHasTransientState calls");
9722        } else if ((hasTransientState && mTransientStateCount == 1) ||
9723                (!hasTransientState && mTransientStateCount == 0)) {
9724            // update flag if we've just incremented up from 0 or decremented down to 0
9725            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
9726                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
9727            if (mParent != null) {
9728                try {
9729                    mParent.childHasTransientStateChanged(this, hasTransientState);
9730                } catch (AbstractMethodError e) {
9731                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9732                            " does not fully implement ViewParent", e);
9733                }
9734            }
9735        }
9736    }
9737
9738    /**
9739     * Returns true if this view is currently attached to a window.
9740     */
9741    public boolean isAttachedToWindow() {
9742        return mAttachInfo != null;
9743    }
9744
9745    /**
9746     * Returns true if this view has been through at least one layout since it
9747     * was last attached to or detached from a window.
9748     */
9749    public boolean isLaidOut() {
9750        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
9751    }
9752
9753    /**
9754     * If this view doesn't do any drawing on its own, set this flag to
9755     * allow further optimizations. By default, this flag is not set on
9756     * View, but could be set on some View subclasses such as ViewGroup.
9757     *
9758     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
9759     * you should clear this flag.
9760     *
9761     * @param willNotDraw whether or not this View draw on its own
9762     */
9763    public void setWillNotDraw(boolean willNotDraw) {
9764        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
9765    }
9766
9767    /**
9768     * Returns whether or not this View draws on its own.
9769     *
9770     * @return true if this view has nothing to draw, false otherwise
9771     */
9772    @ViewDebug.ExportedProperty(category = "drawing")
9773    public boolean willNotDraw() {
9774        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
9775    }
9776
9777    /**
9778     * When a View's drawing cache is enabled, drawing is redirected to an
9779     * offscreen bitmap. Some views, like an ImageView, must be able to
9780     * bypass this mechanism if they already draw a single bitmap, to avoid
9781     * unnecessary usage of the memory.
9782     *
9783     * @param willNotCacheDrawing true if this view does not cache its
9784     *        drawing, false otherwise
9785     */
9786    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
9787        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
9788    }
9789
9790    /**
9791     * Returns whether or not this View can cache its drawing or not.
9792     *
9793     * @return true if this view does not cache its drawing, false otherwise
9794     */
9795    @ViewDebug.ExportedProperty(category = "drawing")
9796    public boolean willNotCacheDrawing() {
9797        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
9798    }
9799
9800    /**
9801     * Indicates whether this view reacts to click events or not.
9802     *
9803     * @return true if the view is clickable, false otherwise
9804     *
9805     * @see #setClickable(boolean)
9806     * @attr ref android.R.styleable#View_clickable
9807     */
9808    @ViewDebug.ExportedProperty
9809    public boolean isClickable() {
9810        return (mViewFlags & CLICKABLE) == CLICKABLE;
9811    }
9812
9813    /**
9814     * Enables or disables click events for this view. When a view
9815     * is clickable it will change its state to "pressed" on every click.
9816     * Subclasses should set the view clickable to visually react to
9817     * user's clicks.
9818     *
9819     * @param clickable true to make the view clickable, false otherwise
9820     *
9821     * @see #isClickable()
9822     * @attr ref android.R.styleable#View_clickable
9823     */
9824    public void setClickable(boolean clickable) {
9825        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
9826    }
9827
9828    /**
9829     * Indicates whether this view reacts to long click events or not.
9830     *
9831     * @return true if the view is long clickable, false otherwise
9832     *
9833     * @see #setLongClickable(boolean)
9834     * @attr ref android.R.styleable#View_longClickable
9835     */
9836    public boolean isLongClickable() {
9837        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9838    }
9839
9840    /**
9841     * Enables or disables long click events for this view. When a view is long
9842     * clickable it reacts to the user holding down the button for a longer
9843     * duration than a tap. This event can either launch the listener or a
9844     * context menu.
9845     *
9846     * @param longClickable true to make the view long clickable, false otherwise
9847     * @see #isLongClickable()
9848     * @attr ref android.R.styleable#View_longClickable
9849     */
9850    public void setLongClickable(boolean longClickable) {
9851        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
9852    }
9853
9854    /**
9855     * Indicates whether this view reacts to context clicks or not.
9856     *
9857     * @return true if the view is context clickable, false otherwise
9858     * @see #setContextClickable(boolean)
9859     * @attr ref android.R.styleable#View_contextClickable
9860     */
9861    public boolean isContextClickable() {
9862        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
9863    }
9864
9865    /**
9866     * Enables or disables context clicking for this view. This event can launch the listener.
9867     *
9868     * @param contextClickable true to make the view react to a context click, false otherwise
9869     * @see #isContextClickable()
9870     * @attr ref android.R.styleable#View_contextClickable
9871     */
9872    public void setContextClickable(boolean contextClickable) {
9873        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
9874    }
9875
9876    /**
9877     * Sets the pressed state for this view and provides a touch coordinate for
9878     * animation hinting.
9879     *
9880     * @param pressed Pass true to set the View's internal state to "pressed",
9881     *            or false to reverts the View's internal state from a
9882     *            previously set "pressed" state.
9883     * @param x The x coordinate of the touch that caused the press
9884     * @param y The y coordinate of the touch that caused the press
9885     */
9886    private void setPressed(boolean pressed, float x, float y) {
9887        if (pressed) {
9888            drawableHotspotChanged(x, y);
9889        }
9890
9891        setPressed(pressed);
9892    }
9893
9894    /**
9895     * Sets the pressed state for this view.
9896     *
9897     * @see #isClickable()
9898     * @see #setClickable(boolean)
9899     *
9900     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
9901     *        the View's internal state from a previously set "pressed" state.
9902     */
9903    public void setPressed(boolean pressed) {
9904        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
9905
9906        if (pressed) {
9907            mPrivateFlags |= PFLAG_PRESSED;
9908        } else {
9909            mPrivateFlags &= ~PFLAG_PRESSED;
9910        }
9911
9912        if (needsRefresh) {
9913            refreshDrawableState();
9914        }
9915        dispatchSetPressed(pressed);
9916    }
9917
9918    /**
9919     * Dispatch setPressed to all of this View's children.
9920     *
9921     * @see #setPressed(boolean)
9922     *
9923     * @param pressed The new pressed state
9924     */
9925    protected void dispatchSetPressed(boolean pressed) {
9926    }
9927
9928    /**
9929     * Indicates whether the view is currently in pressed state. Unless
9930     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
9931     * the pressed state.
9932     *
9933     * @see #setPressed(boolean)
9934     * @see #isClickable()
9935     * @see #setClickable(boolean)
9936     *
9937     * @return true if the view is currently pressed, false otherwise
9938     */
9939    @ViewDebug.ExportedProperty
9940    public boolean isPressed() {
9941        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
9942    }
9943
9944    /**
9945     * @hide
9946     * Indicates whether this view will participate in data collection through
9947     * {@link ViewStructure}.  If true, it will not provide any data
9948     * for itself or its children.  If false, the normal data collection will be allowed.
9949     *
9950     * @return Returns false if assist data collection is not blocked, else true.
9951     *
9952     * @see #setAssistBlocked(boolean)
9953     * @attr ref android.R.styleable#View_assistBlocked
9954     */
9955    public boolean isAssistBlocked() {
9956        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
9957    }
9958
9959    /**
9960     * @hide
9961     * Controls whether assist data collection from this view and its children is enabled
9962     * (that is, whether {@link #onProvideStructure} and
9963     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
9964     * allowing normal assist collection.  Setting this to false will disable assist collection.
9965     *
9966     * @param enabled Set to true to <em>disable</em> assist data collection, or false
9967     * (the default) to allow it.
9968     *
9969     * @see #isAssistBlocked()
9970     * @see #onProvideStructure
9971     * @see #onProvideVirtualStructure
9972     * @attr ref android.R.styleable#View_assistBlocked
9973     */
9974    public void setAssistBlocked(boolean enabled) {
9975        if (enabled) {
9976            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
9977        } else {
9978            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
9979        }
9980    }
9981
9982    /**
9983     * Indicates whether this view will save its state (that is,
9984     * whether its {@link #onSaveInstanceState} method will be called).
9985     *
9986     * @return Returns true if the view state saving is enabled, else false.
9987     *
9988     * @see #setSaveEnabled(boolean)
9989     * @attr ref android.R.styleable#View_saveEnabled
9990     */
9991    public boolean isSaveEnabled() {
9992        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
9993    }
9994
9995    /**
9996     * Controls whether the saving of this view's state is
9997     * enabled (that is, whether its {@link #onSaveInstanceState} method
9998     * will be called).  Note that even if freezing is enabled, the
9999     * view still must have an id assigned to it (via {@link #setId(int)})
10000     * for its state to be saved.  This flag can only disable the
10001     * saving of this view; any child views may still have their state saved.
10002     *
10003     * @param enabled Set to false to <em>disable</em> state saving, or true
10004     * (the default) to allow it.
10005     *
10006     * @see #isSaveEnabled()
10007     * @see #setId(int)
10008     * @see #onSaveInstanceState()
10009     * @attr ref android.R.styleable#View_saveEnabled
10010     */
10011    public void setSaveEnabled(boolean enabled) {
10012        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
10013    }
10014
10015    /**
10016     * Gets whether the framework should discard touches when the view's
10017     * window is obscured by another visible window.
10018     * Refer to the {@link View} security documentation for more details.
10019     *
10020     * @return True if touch filtering is enabled.
10021     *
10022     * @see #setFilterTouchesWhenObscured(boolean)
10023     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
10024     */
10025    @ViewDebug.ExportedProperty
10026    public boolean getFilterTouchesWhenObscured() {
10027        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
10028    }
10029
10030    /**
10031     * Sets whether the framework should discard touches when the view's
10032     * window is obscured by another visible window.
10033     * Refer to the {@link View} security documentation for more details.
10034     *
10035     * @param enabled True if touch filtering should be enabled.
10036     *
10037     * @see #getFilterTouchesWhenObscured
10038     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
10039     */
10040    public void setFilterTouchesWhenObscured(boolean enabled) {
10041        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
10042                FILTER_TOUCHES_WHEN_OBSCURED);
10043    }
10044
10045    /**
10046     * Indicates whether the entire hierarchy under this view will save its
10047     * state when a state saving traversal occurs from its parent.  The default
10048     * is true; if false, these views will not be saved unless
10049     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10050     *
10051     * @return Returns true if the view state saving from parent is enabled, else false.
10052     *
10053     * @see #setSaveFromParentEnabled(boolean)
10054     */
10055    public boolean isSaveFromParentEnabled() {
10056        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
10057    }
10058
10059    /**
10060     * Controls whether the entire hierarchy under this view will save its
10061     * state when a state saving traversal occurs from its parent.  The default
10062     * is true; if false, these views will not be saved unless
10063     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
10064     *
10065     * @param enabled Set to false to <em>disable</em> state saving, or true
10066     * (the default) to allow it.
10067     *
10068     * @see #isSaveFromParentEnabled()
10069     * @see #setId(int)
10070     * @see #onSaveInstanceState()
10071     */
10072    public void setSaveFromParentEnabled(boolean enabled) {
10073        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
10074    }
10075
10076
10077    /**
10078     * Returns whether this View is currently able to take focus.
10079     *
10080     * @return True if this view can take focus, or false otherwise.
10081     */
10082    @ViewDebug.ExportedProperty(category = "focus")
10083    public final boolean isFocusable() {
10084        return FOCUSABLE == (mViewFlags & FOCUSABLE);
10085    }
10086
10087    /**
10088     * Returns the focusable setting for this view.
10089     *
10090     * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}.
10091     * @attr ref android.R.styleable#View_focusable
10092     */
10093    @ViewDebug.ExportedProperty(mapping = {
10094            @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"),
10095            @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"),
10096            @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO")
10097            }, category = "focus")
10098    @Focusable
10099    public int getFocusable() {
10100        return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE;
10101    }
10102
10103    /**
10104     * When a view is focusable, it may not want to take focus when in touch mode.
10105     * For example, a button would like focus when the user is navigating via a D-pad
10106     * so that the user can click on it, but once the user starts touching the screen,
10107     * the button shouldn't take focus
10108     * @return Whether the view is focusable in touch mode.
10109     * @attr ref android.R.styleable#View_focusableInTouchMode
10110     */
10111    @ViewDebug.ExportedProperty(category = "focus")
10112    public final boolean isFocusableInTouchMode() {
10113        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
10114    }
10115
10116    /**
10117     * Find the nearest view in the specified direction that can take focus.
10118     * This does not actually give focus to that view.
10119     *
10120     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10121     *
10122     * @return The nearest focusable in the specified direction, or null if none
10123     *         can be found.
10124     */
10125    public View focusSearch(@FocusRealDirection int direction) {
10126        if (mParent != null) {
10127            return mParent.focusSearch(this, direction);
10128        } else {
10129            return null;
10130        }
10131    }
10132
10133    /**
10134     * Returns whether this View is a root of a keyboard navigation cluster.
10135     *
10136     * @return True if this view is a root of a cluster, or false otherwise.
10137     * @attr ref android.R.styleable#View_keyboardNavigationCluster
10138     */
10139    @ViewDebug.ExportedProperty(category = "focus")
10140    public final boolean isKeyboardNavigationCluster() {
10141        return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0;
10142    }
10143
10144    /**
10145     * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters
10146     * will be ignored.
10147     *
10148     * @return the keyboard navigation cluster that this view is in (can be this view)
10149     *         or {@code null} if not in one
10150     */
10151    View findKeyboardNavigationCluster() {
10152        if (mParent instanceof View) {
10153            View cluster = ((View) mParent).findKeyboardNavigationCluster();
10154            if (cluster != null) {
10155                return cluster;
10156            } else if (isKeyboardNavigationCluster()) {
10157                return this;
10158            }
10159        }
10160        return null;
10161    }
10162
10163    /**
10164     * Set whether this view is a root of a keyboard navigation cluster.
10165     *
10166     * @param isCluster If true, this view is a root of a cluster.
10167     *
10168     * @attr ref android.R.styleable#View_keyboardNavigationCluster
10169     */
10170    public void setKeyboardNavigationCluster(boolean isCluster) {
10171        if (isCluster) {
10172            mPrivateFlags3 |= PFLAG3_CLUSTER;
10173        } else {
10174            mPrivateFlags3 &= ~PFLAG3_CLUSTER;
10175        }
10176    }
10177
10178    /**
10179     * Sets this View as the one which receives focus the next time cluster navigation jumps
10180     * to the cluster containing this View. This does NOT change focus even if the cluster
10181     * containing this view is current.
10182     *
10183     * @hide
10184     */
10185    public final void setFocusedInCluster() {
10186        setFocusedInCluster(findKeyboardNavigationCluster());
10187    }
10188
10189    private void setFocusedInCluster(View cluster) {
10190        if (this instanceof ViewGroup) {
10191            ((ViewGroup) this).mFocusedInCluster = null;
10192        }
10193        if (cluster == this) {
10194            return;
10195        }
10196        ViewParent parent = mParent;
10197        View child = this;
10198        while (parent instanceof ViewGroup) {
10199            ((ViewGroup) parent).mFocusedInCluster = child;
10200            if (parent == cluster) {
10201                break;
10202            }
10203            child = (View) parent;
10204            parent = parent.getParent();
10205        }
10206    }
10207
10208    private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) {
10209        if (oldFocus != null) {
10210            View oldCluster = oldFocus.findKeyboardNavigationCluster();
10211            View cluster = findKeyboardNavigationCluster();
10212            if (oldCluster != cluster) {
10213                // Going from one cluster to another, so save last-focused.
10214                // This covers cluster jumps because they are always FOCUS_DOWN
10215                oldFocus.setFocusedInCluster(oldCluster);
10216                if (!(oldFocus.mParent instanceof ViewGroup)) {
10217                    return;
10218                }
10219                if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
10220                    // This is a result of ordered navigation so consider navigation through
10221                    // the previous cluster "complete" and clear its last-focused memory.
10222                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10223                } else if (oldFocus instanceof ViewGroup
10224                        && ((ViewGroup) oldFocus).getDescendantFocusability()
10225                                == ViewGroup.FOCUS_AFTER_DESCENDANTS
10226                        && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
10227                    // This means oldFocus is not focusable since it obviously has a focusable
10228                    // child (this). Don't restore focus to it in the future.
10229                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
10230                }
10231            }
10232        }
10233    }
10234
10235    /**
10236     * Returns whether this View should receive focus when the focus is restored for the view
10237     * hierarchy containing this view.
10238     * <p>
10239     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10240     * window or serves as a target of cluster navigation.
10241     *
10242     * @see #restoreDefaultFocus()
10243     *
10244     * @return {@code true} if this view is the default-focus view, {@code false} otherwise
10245     * @attr ref android.R.styleable#View_focusedByDefault
10246     */
10247    @ViewDebug.ExportedProperty(category = "focus")
10248    public final boolean isFocusedByDefault() {
10249        return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0;
10250    }
10251
10252    /**
10253     * Sets whether this View should receive focus when the focus is restored for the view
10254     * hierarchy containing this view.
10255     * <p>
10256     * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
10257     * window or serves as a target of cluster navigation.
10258     *
10259     * @param isFocusedByDefault {@code true} to set this view as the default-focus view,
10260     *                           {@code false} otherwise.
10261     *
10262     * @see #restoreDefaultFocus()
10263     *
10264     * @attr ref android.R.styleable#View_focusedByDefault
10265     */
10266    public void setFocusedByDefault(boolean isFocusedByDefault) {
10267        if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) {
10268            return;
10269        }
10270
10271        if (isFocusedByDefault) {
10272            mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT;
10273        } else {
10274            mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT;
10275        }
10276
10277        if (mParent instanceof ViewGroup) {
10278            if (isFocusedByDefault) {
10279                ((ViewGroup) mParent).setDefaultFocus(this);
10280            } else {
10281                ((ViewGroup) mParent).clearDefaultFocus(this);
10282            }
10283        }
10284    }
10285
10286    /**
10287     * Returns whether the view hierarchy with this view as a root contain a default-focus view.
10288     *
10289     * @return {@code true} if this view has default focus, {@code false} otherwise
10290     */
10291    boolean hasDefaultFocus() {
10292        return isFocusedByDefault();
10293    }
10294
10295    /**
10296     * Find the nearest keyboard navigation cluster in the specified direction.
10297     * This does not actually give focus to that cluster.
10298     *
10299     * @param currentCluster The starting point of the search. Null means the current cluster is not
10300     *                       found yet
10301     * @param direction Direction to look
10302     *
10303     * @return The nearest keyboard navigation cluster in the specified direction, or null if none
10304     *         can be found
10305     */
10306    public View keyboardNavigationClusterSearch(View currentCluster,
10307            @FocusDirection int direction) {
10308        if (isKeyboardNavigationCluster()) {
10309            currentCluster = this;
10310        }
10311        if (isRootNamespace()) {
10312            // Root namespace means we should consider ourselves the top of the
10313            // tree for group searching; otherwise we could be group searching
10314            // into other tabs.  see LocalActivityManager and TabHost for more info.
10315            return FocusFinder.getInstance().findNextKeyboardNavigationCluster(
10316                    this, currentCluster, direction);
10317        } else if (mParent != null) {
10318            return mParent.keyboardNavigationClusterSearch(currentCluster, direction);
10319        }
10320        return null;
10321    }
10322
10323    /**
10324     * This method is the last chance for the focused view and its ancestors to
10325     * respond to an arrow key. This is called when the focused view did not
10326     * consume the key internally, nor could the view system find a new view in
10327     * the requested direction to give focus to.
10328     *
10329     * @param focused The currently focused view.
10330     * @param direction The direction focus wants to move. One of FOCUS_UP,
10331     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
10332     * @return True if the this view consumed this unhandled move.
10333     */
10334    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
10335        return false;
10336    }
10337
10338    /**
10339     * Sets whether this View should use a default focus highlight when it gets focused but doesn't
10340     * have {@link android.R.attr#state_focused} defined in its background.
10341     *
10342     * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus
10343     *                                      highlight, {@code false} otherwise.
10344     *
10345     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10346     */
10347    public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {
10348        mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled;
10349    }
10350
10351    /**
10352
10353    /**
10354     * Returns whether this View should use a default focus highlight when it gets focused but
10355     * doesn't have {@link android.R.attr#state_focused} defined in its background.
10356     *
10357     * @return True if this View should use a default focus highlight.
10358     * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled
10359     */
10360    @ViewDebug.ExportedProperty(category = "focus")
10361    public final boolean getDefaultFocusHighlightEnabled() {
10362        return mDefaultFocusHighlightEnabled;
10363    }
10364
10365    /**
10366     * If a user manually specified the next view id for a particular direction,
10367     * use the root to look up the view.
10368     * @param root The root view of the hierarchy containing this view.
10369     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
10370     * or FOCUS_BACKWARD.
10371     * @return The user specified next view, or null if there is none.
10372     */
10373    View findUserSetNextFocus(View root, @FocusDirection int direction) {
10374        switch (direction) {
10375            case FOCUS_LEFT:
10376                if (mNextFocusLeftId == View.NO_ID) return null;
10377                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
10378            case FOCUS_RIGHT:
10379                if (mNextFocusRightId == View.NO_ID) return null;
10380                return findViewInsideOutShouldExist(root, mNextFocusRightId);
10381            case FOCUS_UP:
10382                if (mNextFocusUpId == View.NO_ID) return null;
10383                return findViewInsideOutShouldExist(root, mNextFocusUpId);
10384            case FOCUS_DOWN:
10385                if (mNextFocusDownId == View.NO_ID) return null;
10386                return findViewInsideOutShouldExist(root, mNextFocusDownId);
10387            case FOCUS_FORWARD:
10388                if (mNextFocusForwardId == View.NO_ID) return null;
10389                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
10390            case FOCUS_BACKWARD: {
10391                if (mID == View.NO_ID) return null;
10392                final int id = mID;
10393                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
10394                    @Override
10395                    public boolean test(View t) {
10396                        return t.mNextFocusForwardId == id;
10397                    }
10398                });
10399            }
10400        }
10401        return null;
10402    }
10403
10404    /**
10405     * If a user manually specified the next keyboard-navigation cluster for a particular direction,
10406     * use the root to look up the view.
10407     *
10408     * @param root the root view of the hierarchy containing this view
10409     * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD}
10410     * @return the user-specified next cluster, or {@code null} if there is none
10411     */
10412    View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) {
10413        switch (direction) {
10414            case FOCUS_FORWARD:
10415                if (mNextClusterForwardId == View.NO_ID) return null;
10416                return findViewInsideOutShouldExist(root, mNextClusterForwardId);
10417            case FOCUS_BACKWARD: {
10418                if (mID == View.NO_ID) return null;
10419                final int id = mID;
10420                return root.findViewByPredicateInsideOut(this,
10421                        (Predicate<View>) t -> t.mNextClusterForwardId == id);
10422            }
10423        }
10424        return null;
10425    }
10426
10427    private View findViewInsideOutShouldExist(View root, int id) {
10428        if (mMatchIdPredicate == null) {
10429            mMatchIdPredicate = new MatchIdPredicate();
10430        }
10431        mMatchIdPredicate.mId = id;
10432        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
10433        if (result == null) {
10434            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
10435        }
10436        return result;
10437    }
10438
10439    /**
10440     * Find and return all focusable views that are descendants of this view,
10441     * possibly including this view if it is focusable itself.
10442     *
10443     * @param direction The direction of the focus
10444     * @return A list of focusable views
10445     */
10446    public ArrayList<View> getFocusables(@FocusDirection int direction) {
10447        ArrayList<View> result = new ArrayList<View>(24);
10448        addFocusables(result, direction);
10449        return result;
10450    }
10451
10452    /**
10453     * Add any focusable views that are descendants of this view (possibly
10454     * including this view if it is focusable itself) to views.  If we are in touch mode,
10455     * only add views that are also focusable in touch mode.
10456     *
10457     * @param views Focusable views found so far
10458     * @param direction The direction of the focus
10459     */
10460    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
10461        addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL);
10462    }
10463
10464    /**
10465     * Adds any focusable views that are descendants of this view (possibly
10466     * including this view if it is focusable itself) to views. This method
10467     * adds all focusable views regardless if we are in touch mode or
10468     * only views focusable in touch mode if we are in touch mode or
10469     * only views that can take accessibility focus if accessibility is enabled
10470     * depending on the focusable mode parameter.
10471     *
10472     * @param views Focusable views found so far or null if all we are interested is
10473     *        the number of focusables.
10474     * @param direction The direction of the focus.
10475     * @param focusableMode The type of focusables to be added.
10476     *
10477     * @see #FOCUSABLES_ALL
10478     * @see #FOCUSABLES_TOUCH_MODE
10479     */
10480    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
10481            @FocusableMode int focusableMode) {
10482        if (views == null) {
10483            return;
10484        }
10485        if (!isFocusable()) {
10486            return;
10487        }
10488        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
10489                && !isFocusableInTouchMode()) {
10490            return;
10491        }
10492        views.add(this);
10493    }
10494
10495    /**
10496     * Adds any keyboard navigation cluster roots that are descendants of this view (possibly
10497     * including this view if it is a cluster root itself) to views.
10498     *
10499     * @param views Keyboard navigation cluster roots found so far
10500     * @param direction Direction to look
10501     */
10502    public void addKeyboardNavigationClusters(
10503            @NonNull Collection<View> views,
10504            int direction) {
10505        if (!isKeyboardNavigationCluster()) {
10506            return;
10507        }
10508        if (!hasFocusable()) {
10509            return;
10510        }
10511        views.add(this);
10512    }
10513
10514    /**
10515     * Finds the Views that contain given text. The containment is case insensitive.
10516     * The search is performed by either the text that the View renders or the content
10517     * description that describes the view for accessibility purposes and the view does
10518     * not render or both. Clients can specify how the search is to be performed via
10519     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
10520     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
10521     *
10522     * @param outViews The output list of matching Views.
10523     * @param searched The text to match against.
10524     *
10525     * @see #FIND_VIEWS_WITH_TEXT
10526     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
10527     * @see #setContentDescription(CharSequence)
10528     */
10529    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
10530            @FindViewFlags int flags) {
10531        if (getAccessibilityNodeProvider() != null) {
10532            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
10533                outViews.add(this);
10534            }
10535        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
10536                && (searched != null && searched.length() > 0)
10537                && (mContentDescription != null && mContentDescription.length() > 0)) {
10538            String searchedLowerCase = searched.toString().toLowerCase();
10539            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
10540            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
10541                outViews.add(this);
10542            }
10543        }
10544    }
10545
10546    /**
10547     * Find and return all touchable views that are descendants of this view,
10548     * possibly including this view if it is touchable itself.
10549     *
10550     * @return A list of touchable views
10551     */
10552    public ArrayList<View> getTouchables() {
10553        ArrayList<View> result = new ArrayList<View>();
10554        addTouchables(result);
10555        return result;
10556    }
10557
10558    /**
10559     * Add any touchable views that are descendants of this view (possibly
10560     * including this view if it is touchable itself) to views.
10561     *
10562     * @param views Touchable views found so far
10563     */
10564    public void addTouchables(ArrayList<View> views) {
10565        final int viewFlags = mViewFlags;
10566
10567        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10568                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
10569                && (viewFlags & ENABLED_MASK) == ENABLED) {
10570            views.add(this);
10571        }
10572    }
10573
10574    /**
10575     * Returns whether this View is accessibility focused.
10576     *
10577     * @return True if this View is accessibility focused.
10578     */
10579    public boolean isAccessibilityFocused() {
10580        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
10581    }
10582
10583    /**
10584     * Call this to try to give accessibility focus to this view.
10585     *
10586     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
10587     * returns false or the view is no visible or the view already has accessibility
10588     * focus.
10589     *
10590     * See also {@link #focusSearch(int)}, which is what you call to say that you
10591     * have focus, and you want your parent to look for the next one.
10592     *
10593     * @return Whether this view actually took accessibility focus.
10594     *
10595     * @hide
10596     */
10597    public boolean requestAccessibilityFocus() {
10598        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
10599        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
10600            return false;
10601        }
10602        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10603            return false;
10604        }
10605        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
10606            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
10607            ViewRootImpl viewRootImpl = getViewRootImpl();
10608            if (viewRootImpl != null) {
10609                viewRootImpl.setAccessibilityFocus(this, null);
10610            }
10611            invalidate();
10612            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
10613            return true;
10614        }
10615        return false;
10616    }
10617
10618    /**
10619     * Call this to try to clear accessibility focus of this view.
10620     *
10621     * See also {@link #focusSearch(int)}, which is what you call to say that you
10622     * have focus, and you want your parent to look for the next one.
10623     *
10624     * @hide
10625     */
10626    public void clearAccessibilityFocus() {
10627        clearAccessibilityFocusNoCallbacks(0);
10628
10629        // Clear the global reference of accessibility focus if this view or
10630        // any of its descendants had accessibility focus. This will NOT send
10631        // an event or update internal state if focus is cleared from a
10632        // descendant view, which may leave views in inconsistent states.
10633        final ViewRootImpl viewRootImpl = getViewRootImpl();
10634        if (viewRootImpl != null) {
10635            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
10636            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
10637                viewRootImpl.setAccessibilityFocus(null, null);
10638            }
10639        }
10640    }
10641
10642    private void sendAccessibilityHoverEvent(int eventType) {
10643        // Since we are not delivering to a client accessibility events from not
10644        // important views (unless the clinet request that) we need to fire the
10645        // event from the deepest view exposed to the client. As a consequence if
10646        // the user crosses a not exposed view the client will see enter and exit
10647        // of the exposed predecessor followed by and enter and exit of that same
10648        // predecessor when entering and exiting the not exposed descendant. This
10649        // is fine since the client has a clear idea which view is hovered at the
10650        // price of a couple more events being sent. This is a simple and
10651        // working solution.
10652        View source = this;
10653        while (true) {
10654            if (source.includeForAccessibility()) {
10655                source.sendAccessibilityEvent(eventType);
10656                return;
10657            }
10658            ViewParent parent = source.getParent();
10659            if (parent instanceof View) {
10660                source = (View) parent;
10661            } else {
10662                return;
10663            }
10664        }
10665    }
10666
10667    /**
10668     * Clears accessibility focus without calling any callback methods
10669     * normally invoked in {@link #clearAccessibilityFocus()}. This method
10670     * is used separately from that one for clearing accessibility focus when
10671     * giving this focus to another view.
10672     *
10673     * @param action The action, if any, that led to focus being cleared. Set to
10674     * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within
10675     * the window.
10676     */
10677    void clearAccessibilityFocusNoCallbacks(int action) {
10678        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
10679            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
10680            invalidate();
10681            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10682                AccessibilityEvent event = AccessibilityEvent.obtain(
10683                        AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
10684                event.setAction(action);
10685                if (mAccessibilityDelegate != null) {
10686                    mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
10687                } else {
10688                    sendAccessibilityEventUnchecked(event);
10689                }
10690            }
10691        }
10692    }
10693
10694    /**
10695     * Call this to try to give focus to a specific view or to one of its
10696     * descendants.
10697     *
10698     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10699     * false), or if it is focusable and it is not focusable in touch mode
10700     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10701     *
10702     * See also {@link #focusSearch(int)}, which is what you call to say that you
10703     * have focus, and you want your parent to look for the next one.
10704     *
10705     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
10706     * {@link #FOCUS_DOWN} and <code>null</code>.
10707     *
10708     * @return Whether this view or one of its descendants actually took focus.
10709     */
10710    public final boolean requestFocus() {
10711        return requestFocus(View.FOCUS_DOWN);
10712    }
10713
10714    /**
10715     * This will request focus for whichever View was last focused within this
10716     * cluster before a focus-jump out of it.
10717     *
10718     * @hide
10719     */
10720    @TestApi
10721    public boolean restoreFocusInCluster(@FocusRealDirection int direction) {
10722        // Prioritize focusableByDefault over algorithmic focus selection.
10723        if (restoreDefaultFocus()) {
10724            return true;
10725        }
10726        return requestFocus(direction);
10727    }
10728
10729    /**
10730     * This will request focus for whichever View not in a cluster was last focused before a
10731     * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus
10732     * the "first" focusable view it finds.
10733     *
10734     * @hide
10735     */
10736    @TestApi
10737    public boolean restoreFocusNotInCluster() {
10738        return requestFocus(View.FOCUS_DOWN);
10739    }
10740
10741    /**
10742     * Gives focus to the default-focus view in the view hierarchy that has this view as a root.
10743     * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}.
10744     *
10745     * @return Whether this view or one of its descendants actually took focus
10746     */
10747    public boolean restoreDefaultFocus() {
10748        return requestFocus(View.FOCUS_DOWN);
10749    }
10750
10751    /**
10752     * Call this to try to give focus to a specific view or to one of its
10753     * descendants and give it a hint about what direction focus is heading.
10754     *
10755     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10756     * false), or if it is focusable and it is not focusable in touch mode
10757     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10758     *
10759     * See also {@link #focusSearch(int)}, which is what you call to say that you
10760     * have focus, and you want your parent to look for the next one.
10761     *
10762     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
10763     * <code>null</code> set for the previously focused rectangle.
10764     *
10765     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10766     * @return Whether this view or one of its descendants actually took focus.
10767     */
10768    public final boolean requestFocus(int direction) {
10769        return requestFocus(direction, null);
10770    }
10771
10772    /**
10773     * Call this to try to give focus to a specific view or to one of its descendants
10774     * and give it hints about the direction and a specific rectangle that the focus
10775     * is coming from.  The rectangle can help give larger views a finer grained hint
10776     * about where focus is coming from, and therefore, where to show selection, or
10777     * forward focus change internally.
10778     *
10779     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
10780     * false), or if it is focusable and it is not focusable in touch mode
10781     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
10782     *
10783     * A View will not take focus if it is not visible.
10784     *
10785     * A View will not take focus if one of its parents has
10786     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
10787     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
10788     *
10789     * See also {@link #focusSearch(int)}, which is what you call to say that you
10790     * have focus, and you want your parent to look for the next one.
10791     *
10792     * You may wish to override this method if your custom {@link View} has an internal
10793     * {@link View} that it wishes to forward the request to.
10794     *
10795     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
10796     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
10797     *        to give a finer grained hint about where focus is coming from.  May be null
10798     *        if there is no hint.
10799     * @return Whether this view or one of its descendants actually took focus.
10800     */
10801    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
10802        return requestFocusNoSearch(direction, previouslyFocusedRect);
10803    }
10804
10805    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
10806        // need to be focusable
10807        if ((mViewFlags & FOCUSABLE) != FOCUSABLE
10808                || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
10809            return false;
10810        }
10811
10812        // need to be focusable in touch mode if in touch mode
10813        if (isInTouchMode() &&
10814            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
10815               return false;
10816        }
10817
10818        // need to not have any parents blocking us
10819        if (hasAncestorThatBlocksDescendantFocus()) {
10820            return false;
10821        }
10822
10823        handleFocusGainInternal(direction, previouslyFocusedRect);
10824        return true;
10825    }
10826
10827    /**
10828     * Call this to try to give focus to a specific view or to one of its descendants. This is a
10829     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
10830     * touch mode to request focus when they are touched.
10831     *
10832     * @return Whether this view or one of its descendants actually took focus.
10833     *
10834     * @see #isInTouchMode()
10835     *
10836     */
10837    public final boolean requestFocusFromTouch() {
10838        // Leave touch mode if we need to
10839        if (isInTouchMode()) {
10840            ViewRootImpl viewRoot = getViewRootImpl();
10841            if (viewRoot != null) {
10842                viewRoot.ensureTouchMode(false);
10843            }
10844        }
10845        return requestFocus(View.FOCUS_DOWN);
10846    }
10847
10848    /**
10849     * @return Whether any ancestor of this view blocks descendant focus.
10850     */
10851    private boolean hasAncestorThatBlocksDescendantFocus() {
10852        final boolean focusableInTouchMode = isFocusableInTouchMode();
10853        ViewParent ancestor = mParent;
10854        while (ancestor instanceof ViewGroup) {
10855            final ViewGroup vgAncestor = (ViewGroup) ancestor;
10856            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
10857                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
10858                return true;
10859            } else {
10860                ancestor = vgAncestor.getParent();
10861            }
10862        }
10863        return false;
10864    }
10865
10866    /**
10867     * Gets the mode for determining whether this View is important for accessibility.
10868     * A view is important for accessibility if it fires accessibility events and if it
10869     * is reported to accessibility services that query the screen.
10870     *
10871     * @return The mode for determining whether a view is important for accessibility, one
10872     * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES},
10873     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or
10874     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}.
10875     *
10876     * @attr ref android.R.styleable#View_importantForAccessibility
10877     *
10878     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10879     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10880     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10881     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10882     */
10883    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
10884            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
10885            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
10886            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
10887            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
10888                    to = "noHideDescendants")
10889        })
10890    public int getImportantForAccessibility() {
10891        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
10892                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
10893    }
10894
10895    /**
10896     * Sets the live region mode for this view. This indicates to accessibility
10897     * services whether they should automatically notify the user about changes
10898     * to the view's content description or text, or to the content descriptions
10899     * or text of the view's children (where applicable).
10900     * <p>
10901     * For example, in a login screen with a TextView that displays an "incorrect
10902     * password" notification, that view should be marked as a live region with
10903     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10904     * <p>
10905     * To disable change notifications for this view, use
10906     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
10907     * mode for most views.
10908     * <p>
10909     * To indicate that the user should be notified of changes, use
10910     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
10911     * <p>
10912     * If the view's changes should interrupt ongoing speech and notify the user
10913     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
10914     *
10915     * @param mode The live region mode for this view, one of:
10916     *        <ul>
10917     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
10918     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
10919     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
10920     *        </ul>
10921     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10922     */
10923    public void setAccessibilityLiveRegion(int mode) {
10924        if (mode != getAccessibilityLiveRegion()) {
10925            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10926            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
10927                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
10928            notifyViewAccessibilityStateChangedIfNeeded(
10929                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10930        }
10931    }
10932
10933    /**
10934     * Gets the live region mode for this View.
10935     *
10936     * @return The live region mode for the view.
10937     *
10938     * @attr ref android.R.styleable#View_accessibilityLiveRegion
10939     *
10940     * @see #setAccessibilityLiveRegion(int)
10941     */
10942    public int getAccessibilityLiveRegion() {
10943        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
10944                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
10945    }
10946
10947    /**
10948     * Sets how to determine whether this view is important for accessibility
10949     * which is if it fires accessibility events and if it is reported to
10950     * accessibility services that query the screen.
10951     *
10952     * @param mode How to determine whether this view is important for accessibility.
10953     *
10954     * @attr ref android.R.styleable#View_importantForAccessibility
10955     *
10956     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
10957     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
10958     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
10959     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
10960     */
10961    public void setImportantForAccessibility(int mode) {
10962        final int oldMode = getImportantForAccessibility();
10963        if (mode != oldMode) {
10964            final boolean hideDescendants =
10965                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
10966
10967            // If this node or its descendants are no longer important, try to
10968            // clear accessibility focus.
10969            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
10970                final View focusHost = findAccessibilityFocusHost(hideDescendants);
10971                if (focusHost != null) {
10972                    focusHost.clearAccessibilityFocus();
10973                }
10974            }
10975
10976            // If we're moving between AUTO and another state, we might not need
10977            // to send a subtree changed notification. We'll store the computed
10978            // importance, since we'll need to check it later to make sure.
10979            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
10980                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
10981            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
10982            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10983            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
10984                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
10985            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
10986                notifySubtreeAccessibilityStateChangedIfNeeded();
10987            } else {
10988                notifyViewAccessibilityStateChangedIfNeeded(
10989                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10990            }
10991        }
10992    }
10993
10994    /**
10995     * Returns the view within this view's hierarchy that is hosting
10996     * accessibility focus.
10997     *
10998     * @param searchDescendants whether to search for focus in descendant views
10999     * @return the view hosting accessibility focus, or {@code null}
11000     */
11001    private View findAccessibilityFocusHost(boolean searchDescendants) {
11002        if (isAccessibilityFocusedViewOrHost()) {
11003            return this;
11004        }
11005
11006        if (searchDescendants) {
11007            final ViewRootImpl viewRoot = getViewRootImpl();
11008            if (viewRoot != null) {
11009                final View focusHost = viewRoot.getAccessibilityFocusedHost();
11010                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
11011                    return focusHost;
11012                }
11013            }
11014        }
11015
11016        return null;
11017    }
11018
11019    /**
11020     * Computes whether this view should be exposed for accessibility. In
11021     * general, views that are interactive or provide information are exposed
11022     * while views that serve only as containers are hidden.
11023     * <p>
11024     * If an ancestor of this view has importance
11025     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
11026     * returns <code>false</code>.
11027     * <p>
11028     * Otherwise, the value is computed according to the view's
11029     * {@link #getImportantForAccessibility()} value:
11030     * <ol>
11031     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
11032     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
11033     * </code>
11034     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
11035     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
11036     * view satisfies any of the following:
11037     * <ul>
11038     * <li>Is actionable, e.g. {@link #isClickable()},
11039     * {@link #isLongClickable()}, or {@link #isFocusable()}
11040     * <li>Has an {@link AccessibilityDelegate}
11041     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
11042     * {@link OnKeyListener}, etc.
11043     * <li>Is an accessibility live region, e.g.
11044     * {@link #getAccessibilityLiveRegion()} is not
11045     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
11046     * </ul>
11047     * </ol>
11048     *
11049     * @return Whether the view is exposed for accessibility.
11050     * @see #setImportantForAccessibility(int)
11051     * @see #getImportantForAccessibility()
11052     */
11053    public boolean isImportantForAccessibility() {
11054        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
11055                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
11056        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
11057                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11058            return false;
11059        }
11060
11061        // Check parent mode to ensure we're not hidden.
11062        ViewParent parent = mParent;
11063        while (parent instanceof View) {
11064            if (((View) parent).getImportantForAccessibility()
11065                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
11066                return false;
11067            }
11068            parent = parent.getParent();
11069        }
11070
11071        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
11072                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
11073                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
11074    }
11075
11076    /**
11077     * Gets the parent for accessibility purposes. Note that the parent for
11078     * accessibility is not necessary the immediate parent. It is the first
11079     * predecessor that is important for accessibility.
11080     *
11081     * @return The parent for accessibility purposes.
11082     */
11083    public ViewParent getParentForAccessibility() {
11084        if (mParent instanceof View) {
11085            View parentView = (View) mParent;
11086            if (parentView.includeForAccessibility()) {
11087                return mParent;
11088            } else {
11089                return mParent.getParentForAccessibility();
11090            }
11091        }
11092        return null;
11093    }
11094
11095    /**
11096     * Adds the children of this View relevant for accessibility to the given list
11097     * as output. Since some Views are not important for accessibility the added
11098     * child views are not necessarily direct children of this view, rather they are
11099     * the first level of descendants important for accessibility.
11100     *
11101     * @param outChildren The output list that will receive children for accessibility.
11102     */
11103    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
11104
11105    }
11106
11107    /**
11108     * Whether to regard this view for accessibility. A view is regarded for
11109     * accessibility if it is important for accessibility or the querying
11110     * accessibility service has explicitly requested that view not
11111     * important for accessibility are regarded.
11112     *
11113     * @return Whether to regard the view for accessibility.
11114     *
11115     * @hide
11116     */
11117    public boolean includeForAccessibility() {
11118        if (mAttachInfo != null) {
11119            return (mAttachInfo.mAccessibilityFetchFlags
11120                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
11121                    || isImportantForAccessibility();
11122        }
11123        return false;
11124    }
11125
11126    /**
11127     * Returns whether the View is considered actionable from
11128     * accessibility perspective. Such view are important for
11129     * accessibility.
11130     *
11131     * @return True if the view is actionable for accessibility.
11132     *
11133     * @hide
11134     */
11135    public boolean isActionableForAccessibility() {
11136        return (isClickable() || isLongClickable() || isFocusable());
11137    }
11138
11139    /**
11140     * Returns whether the View has registered callbacks which makes it
11141     * important for accessibility.
11142     *
11143     * @return True if the view is actionable for accessibility.
11144     */
11145    private boolean hasListenersForAccessibility() {
11146        ListenerInfo info = getListenerInfo();
11147        return mTouchDelegate != null || info.mOnKeyListener != null
11148                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
11149                || info.mOnHoverListener != null || info.mOnDragListener != null;
11150    }
11151
11152    /**
11153     * Notifies that the accessibility state of this view changed. The change
11154     * is local to this view and does not represent structural changes such
11155     * as children and parent. For example, the view became focusable. The
11156     * notification is at at most once every
11157     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11158     * to avoid unnecessary load to the system. Also once a view has a pending
11159     * notification this method is a NOP until the notification has been sent.
11160     *
11161     * @hide
11162     */
11163    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
11164        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11165            return;
11166        }
11167        if (mSendViewStateChangedAccessibilityEvent == null) {
11168            mSendViewStateChangedAccessibilityEvent =
11169                    new SendViewStateChangedAccessibilityEvent();
11170        }
11171        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
11172    }
11173
11174    /**
11175     * Notifies that the accessibility state of this view changed. The change
11176     * is *not* local to this view and does represent structural changes such
11177     * as children and parent. For example, the view size changed. The
11178     * notification is at at most once every
11179     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
11180     * to avoid unnecessary load to the system. Also once a view has a pending
11181     * notification this method is a NOP until the notification has been sent.
11182     *
11183     * @hide
11184     */
11185    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
11186        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
11187            return;
11188        }
11189        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
11190            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11191            if (mParent != null) {
11192                try {
11193                    mParent.notifySubtreeAccessibilityStateChanged(
11194                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
11195                } catch (AbstractMethodError e) {
11196                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
11197                            " does not fully implement ViewParent", e);
11198                }
11199            }
11200        }
11201    }
11202
11203    /**
11204     * Change the visibility of the View without triggering any other changes. This is
11205     * important for transitions, where visibility changes should not adjust focus or
11206     * trigger a new layout. This is only used when the visibility has already been changed
11207     * and we need a transient value during an animation. When the animation completes,
11208     * the original visibility value is always restored.
11209     *
11210     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
11211     * @hide
11212     */
11213    public void setTransitionVisibility(@Visibility int visibility) {
11214        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
11215    }
11216
11217    /**
11218     * Reset the flag indicating the accessibility state of the subtree rooted
11219     * at this view changed.
11220     */
11221    void resetSubtreeAccessibilityStateChanged() {
11222        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
11223    }
11224
11225    /**
11226     * Report an accessibility action to this view's parents for delegated processing.
11227     *
11228     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
11229     * call this method to delegate an accessibility action to a supporting parent. If the parent
11230     * returns true from its
11231     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
11232     * method this method will return true to signify that the action was consumed.</p>
11233     *
11234     * <p>This method is useful for implementing nested scrolling child views. If
11235     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
11236     * a custom view implementation may invoke this method to allow a parent to consume the
11237     * scroll first. If this method returns true the custom view should skip its own scrolling
11238     * behavior.</p>
11239     *
11240     * @param action Accessibility action to delegate
11241     * @param arguments Optional action arguments
11242     * @return true if the action was consumed by a parent
11243     */
11244    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
11245        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
11246            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
11247                return true;
11248            }
11249        }
11250        return false;
11251    }
11252
11253    /**
11254     * Performs the specified accessibility action on the view. For
11255     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
11256     * <p>
11257     * If an {@link AccessibilityDelegate} has been specified via calling
11258     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
11259     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
11260     * is responsible for handling this call.
11261     * </p>
11262     *
11263     * <p>The default implementation will delegate
11264     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
11265     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
11266     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
11267     *
11268     * @param action The action to perform.
11269     * @param arguments Optional action arguments.
11270     * @return Whether the action was performed.
11271     */
11272    public boolean performAccessibilityAction(int action, Bundle arguments) {
11273      if (mAccessibilityDelegate != null) {
11274          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
11275      } else {
11276          return performAccessibilityActionInternal(action, arguments);
11277      }
11278    }
11279
11280   /**
11281    * @see #performAccessibilityAction(int, Bundle)
11282    *
11283    * Note: Called from the default {@link AccessibilityDelegate}.
11284    *
11285    * @hide
11286    */
11287    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
11288        if (isNestedScrollingEnabled()
11289                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
11290                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
11291                || action == R.id.accessibilityActionScrollUp
11292                || action == R.id.accessibilityActionScrollLeft
11293                || action == R.id.accessibilityActionScrollDown
11294                || action == R.id.accessibilityActionScrollRight)) {
11295            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
11296                return true;
11297            }
11298        }
11299
11300        switch (action) {
11301            case AccessibilityNodeInfo.ACTION_CLICK: {
11302                if (isClickable()) {
11303                    performClick();
11304                    return true;
11305                }
11306            } break;
11307            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
11308                if (isLongClickable()) {
11309                    performLongClick();
11310                    return true;
11311                }
11312            } break;
11313            case AccessibilityNodeInfo.ACTION_FOCUS: {
11314                if (!hasFocus()) {
11315                    // Get out of touch mode since accessibility
11316                    // wants to move focus around.
11317                    getViewRootImpl().ensureTouchMode(false);
11318                    return requestFocus();
11319                }
11320            } break;
11321            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
11322                if (hasFocus()) {
11323                    clearFocus();
11324                    return !isFocused();
11325                }
11326            } break;
11327            case AccessibilityNodeInfo.ACTION_SELECT: {
11328                if (!isSelected()) {
11329                    setSelected(true);
11330                    return isSelected();
11331                }
11332            } break;
11333            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
11334                if (isSelected()) {
11335                    setSelected(false);
11336                    return !isSelected();
11337                }
11338            } break;
11339            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
11340                if (!isAccessibilityFocused()) {
11341                    return requestAccessibilityFocus();
11342                }
11343            } break;
11344            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
11345                if (isAccessibilityFocused()) {
11346                    clearAccessibilityFocus();
11347                    return true;
11348                }
11349            } break;
11350            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
11351                if (arguments != null) {
11352                    final int granularity = arguments.getInt(
11353                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11354                    final boolean extendSelection = arguments.getBoolean(
11355                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11356                    return traverseAtGranularity(granularity, true, extendSelection);
11357                }
11358            } break;
11359            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
11360                if (arguments != null) {
11361                    final int granularity = arguments.getInt(
11362                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
11363                    final boolean extendSelection = arguments.getBoolean(
11364                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
11365                    return traverseAtGranularity(granularity, false, extendSelection);
11366                }
11367            } break;
11368            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
11369                CharSequence text = getIterableTextForAccessibility();
11370                if (text == null) {
11371                    return false;
11372                }
11373                final int start = (arguments != null) ? arguments.getInt(
11374                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
11375                final int end = (arguments != null) ? arguments.getInt(
11376                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
11377                // Only cursor position can be specified (selection length == 0)
11378                if ((getAccessibilitySelectionStart() != start
11379                        || getAccessibilitySelectionEnd() != end)
11380                        && (start == end)) {
11381                    setAccessibilitySelection(start, end);
11382                    notifyViewAccessibilityStateChangedIfNeeded(
11383                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11384                    return true;
11385                }
11386            } break;
11387            case R.id.accessibilityActionShowOnScreen: {
11388                if (mAttachInfo != null) {
11389                    final Rect r = mAttachInfo.mTmpInvalRect;
11390                    getDrawingRect(r);
11391                    return requestRectangleOnScreen(r, true);
11392                }
11393            } break;
11394            case R.id.accessibilityActionContextClick: {
11395                if (isContextClickable()) {
11396                    performContextClick();
11397                    return true;
11398                }
11399            } break;
11400        }
11401        return false;
11402    }
11403
11404    private boolean traverseAtGranularity(int granularity, boolean forward,
11405            boolean extendSelection) {
11406        CharSequence text = getIterableTextForAccessibility();
11407        if (text == null || text.length() == 0) {
11408            return false;
11409        }
11410        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
11411        if (iterator == null) {
11412            return false;
11413        }
11414        int current = getAccessibilitySelectionEnd();
11415        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11416            current = forward ? 0 : text.length();
11417        }
11418        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
11419        if (range == null) {
11420            return false;
11421        }
11422        final int segmentStart = range[0];
11423        final int segmentEnd = range[1];
11424        int selectionStart;
11425        int selectionEnd;
11426        if (extendSelection && isAccessibilitySelectionExtendable()) {
11427            selectionStart = getAccessibilitySelectionStart();
11428            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
11429                selectionStart = forward ? segmentStart : segmentEnd;
11430            }
11431            selectionEnd = forward ? segmentEnd : segmentStart;
11432        } else {
11433            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
11434        }
11435        setAccessibilitySelection(selectionStart, selectionEnd);
11436        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
11437                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
11438        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
11439        return true;
11440    }
11441
11442    /**
11443     * Gets the text reported for accessibility purposes.
11444     *
11445     * @return The accessibility text.
11446     *
11447     * @hide
11448     */
11449    public CharSequence getIterableTextForAccessibility() {
11450        return getContentDescription();
11451    }
11452
11453    /**
11454     * Gets whether accessibility selection can be extended.
11455     *
11456     * @return If selection is extensible.
11457     *
11458     * @hide
11459     */
11460    public boolean isAccessibilitySelectionExtendable() {
11461        return false;
11462    }
11463
11464    /**
11465     * @hide
11466     */
11467    public int getAccessibilitySelectionStart() {
11468        return mAccessibilityCursorPosition;
11469    }
11470
11471    /**
11472     * @hide
11473     */
11474    public int getAccessibilitySelectionEnd() {
11475        return getAccessibilitySelectionStart();
11476    }
11477
11478    /**
11479     * @hide
11480     */
11481    public void setAccessibilitySelection(int start, int end) {
11482        if (start ==  end && end == mAccessibilityCursorPosition) {
11483            return;
11484        }
11485        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
11486            mAccessibilityCursorPosition = start;
11487        } else {
11488            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
11489        }
11490        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
11491    }
11492
11493    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
11494            int fromIndex, int toIndex) {
11495        if (mParent == null) {
11496            return;
11497        }
11498        AccessibilityEvent event = AccessibilityEvent.obtain(
11499                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
11500        onInitializeAccessibilityEvent(event);
11501        onPopulateAccessibilityEvent(event);
11502        event.setFromIndex(fromIndex);
11503        event.setToIndex(toIndex);
11504        event.setAction(action);
11505        event.setMovementGranularity(granularity);
11506        mParent.requestSendAccessibilityEvent(this, event);
11507    }
11508
11509    /**
11510     * @hide
11511     */
11512    public TextSegmentIterator getIteratorForGranularity(int granularity) {
11513        switch (granularity) {
11514            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
11515                CharSequence text = getIterableTextForAccessibility();
11516                if (text != null && text.length() > 0) {
11517                    CharacterTextSegmentIterator iterator =
11518                        CharacterTextSegmentIterator.getInstance(
11519                                mContext.getResources().getConfiguration().locale);
11520                    iterator.initialize(text.toString());
11521                    return iterator;
11522                }
11523            } break;
11524            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
11525                CharSequence text = getIterableTextForAccessibility();
11526                if (text != null && text.length() > 0) {
11527                    WordTextSegmentIterator iterator =
11528                        WordTextSegmentIterator.getInstance(
11529                                mContext.getResources().getConfiguration().locale);
11530                    iterator.initialize(text.toString());
11531                    return iterator;
11532                }
11533            } break;
11534            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
11535                CharSequence text = getIterableTextForAccessibility();
11536                if (text != null && text.length() > 0) {
11537                    ParagraphTextSegmentIterator iterator =
11538                        ParagraphTextSegmentIterator.getInstance();
11539                    iterator.initialize(text.toString());
11540                    return iterator;
11541                }
11542            } break;
11543        }
11544        return null;
11545    }
11546
11547    /**
11548     * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()}
11549     * and {@link #onFinishTemporaryDetach()}.
11550     *
11551     * <p>This method always returns {@code true} when called directly or indirectly from
11552     * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from
11553     * {@link #onFinishTemporaryDetach()}, however, depends on the OS version.
11554     * <ul>
11555     *     <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li>
11556     *     <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li>
11557     * </ul>
11558     * </p>
11559     *
11560     * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()}
11561     * and {@link #onFinishTemporaryDetach()}.
11562     */
11563    public final boolean isTemporarilyDetached() {
11564        return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0;
11565    }
11566
11567    /**
11568     * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is
11569     * a container View.
11570     */
11571    @CallSuper
11572    public void dispatchStartTemporaryDetach() {
11573        mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH;
11574        notifyEnterOrExitForAutoFillIfNeeded(false);
11575        onStartTemporaryDetach();
11576    }
11577
11578    /**
11579     * This is called when a container is going to temporarily detach a child, with
11580     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
11581     * It will either be followed by {@link #onFinishTemporaryDetach()} or
11582     * {@link #onDetachedFromWindow()} when the container is done.
11583     */
11584    public void onStartTemporaryDetach() {
11585        removeUnsetPressCallback();
11586        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
11587    }
11588
11589    /**
11590     * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is
11591     * a container View.
11592     */
11593    @CallSuper
11594    public void dispatchFinishTemporaryDetach() {
11595        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
11596        onFinishTemporaryDetach();
11597        if (hasWindowFocus() && hasFocus()) {
11598            InputMethodManager.getInstance().focusIn(this);
11599        }
11600        notifyEnterOrExitForAutoFillIfNeeded(true);
11601    }
11602
11603    /**
11604     * Called after {@link #onStartTemporaryDetach} when the container is done
11605     * changing the view.
11606     */
11607    public void onFinishTemporaryDetach() {
11608    }
11609
11610    /**
11611     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
11612     * for this view's window.  Returns null if the view is not currently attached
11613     * to the window.  Normally you will not need to use this directly, but
11614     * just use the standard high-level event callbacks like
11615     * {@link #onKeyDown(int, KeyEvent)}.
11616     */
11617    public KeyEvent.DispatcherState getKeyDispatcherState() {
11618        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
11619    }
11620
11621    /**
11622     * Dispatch a key event before it is processed by any input method
11623     * associated with the view hierarchy.  This can be used to intercept
11624     * key events in special situations before the IME consumes them; a
11625     * typical example would be handling the BACK key to update the application's
11626     * UI instead of allowing the IME to see it and close itself.
11627     *
11628     * @param event The key event to be dispatched.
11629     * @return True if the event was handled, false otherwise.
11630     */
11631    public boolean dispatchKeyEventPreIme(KeyEvent event) {
11632        return onKeyPreIme(event.getKeyCode(), event);
11633    }
11634
11635    /**
11636     * Dispatch a key event to the next view on the focus path. This path runs
11637     * from the top of the view tree down to the currently focused view. If this
11638     * view has focus, it will dispatch to itself. Otherwise it will dispatch
11639     * the next node down the focus path. This method also fires any key
11640     * listeners.
11641     *
11642     * @param event The key event to be dispatched.
11643     * @return True if the event was handled, false otherwise.
11644     */
11645    public boolean dispatchKeyEvent(KeyEvent event) {
11646        if (mInputEventConsistencyVerifier != null) {
11647            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
11648        }
11649
11650        // Give any attached key listener a first crack at the event.
11651        //noinspection SimplifiableIfStatement
11652        ListenerInfo li = mListenerInfo;
11653        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
11654                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
11655            return true;
11656        }
11657
11658        if (event.dispatch(this, mAttachInfo != null
11659                ? mAttachInfo.mKeyDispatchState : null, this)) {
11660            return true;
11661        }
11662
11663        if (mInputEventConsistencyVerifier != null) {
11664            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11665        }
11666        return false;
11667    }
11668
11669    /**
11670     * Dispatches a key shortcut event.
11671     *
11672     * @param event The key event to be dispatched.
11673     * @return True if the event was handled by the view, false otherwise.
11674     */
11675    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
11676        return onKeyShortcut(event.getKeyCode(), event);
11677    }
11678
11679    /**
11680     * Pass the touch screen motion event down to the target view, or this
11681     * view if it is the target.
11682     *
11683     * @param event The motion event to be dispatched.
11684     * @return True if the event was handled by the view, false otherwise.
11685     */
11686    public boolean dispatchTouchEvent(MotionEvent event) {
11687        // If the event should be handled by accessibility focus first.
11688        if (event.isTargetAccessibilityFocus()) {
11689            // We don't have focus or no virtual descendant has it, do not handle the event.
11690            if (!isAccessibilityFocusedViewOrHost()) {
11691                return false;
11692            }
11693            // We have focus and got the event, then use normal event dispatch.
11694            event.setTargetAccessibilityFocus(false);
11695        }
11696
11697        boolean result = false;
11698
11699        if (mInputEventConsistencyVerifier != null) {
11700            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
11701        }
11702
11703        final int actionMasked = event.getActionMasked();
11704        if (actionMasked == MotionEvent.ACTION_DOWN) {
11705            // Defensive cleanup for new gesture
11706            stopNestedScroll();
11707        }
11708
11709        if (onFilterTouchEventForSecurity(event)) {
11710            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
11711                result = true;
11712            }
11713            //noinspection SimplifiableIfStatement
11714            ListenerInfo li = mListenerInfo;
11715            if (li != null && li.mOnTouchListener != null
11716                    && (mViewFlags & ENABLED_MASK) == ENABLED
11717                    && li.mOnTouchListener.onTouch(this, event)) {
11718                result = true;
11719            }
11720
11721            if (!result && onTouchEvent(event)) {
11722                result = true;
11723            }
11724        }
11725
11726        if (!result && mInputEventConsistencyVerifier != null) {
11727            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11728        }
11729
11730        // Clean up after nested scrolls if this is the end of a gesture;
11731        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
11732        // of the gesture.
11733        if (actionMasked == MotionEvent.ACTION_UP ||
11734                actionMasked == MotionEvent.ACTION_CANCEL ||
11735                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
11736            stopNestedScroll();
11737        }
11738
11739        return result;
11740    }
11741
11742    boolean isAccessibilityFocusedViewOrHost() {
11743        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
11744                .getAccessibilityFocusedHost() == this);
11745    }
11746
11747    /**
11748     * Filter the touch event to apply security policies.
11749     *
11750     * @param event The motion event to be filtered.
11751     * @return True if the event should be dispatched, false if the event should be dropped.
11752     *
11753     * @see #getFilterTouchesWhenObscured
11754     */
11755    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
11756        //noinspection RedundantIfStatement
11757        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
11758                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
11759            // Window is obscured, drop this touch.
11760            return false;
11761        }
11762        return true;
11763    }
11764
11765    /**
11766     * Pass a trackball motion event down to the focused view.
11767     *
11768     * @param event The motion event to be dispatched.
11769     * @return True if the event was handled by the view, false otherwise.
11770     */
11771    public boolean dispatchTrackballEvent(MotionEvent event) {
11772        if (mInputEventConsistencyVerifier != null) {
11773            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
11774        }
11775
11776        return onTrackballEvent(event);
11777    }
11778
11779    /**
11780     * Pass a captured pointer event down to the focused view.
11781     *
11782     * @param event The motion event to be dispatched.
11783     * @return True if the event was handled by the view, false otherwise.
11784     */
11785    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
11786        if (!hasPointerCapture()) {
11787            return false;
11788        }
11789        //noinspection SimplifiableIfStatement
11790        ListenerInfo li = mListenerInfo;
11791        if (li != null && li.mOnCapturedPointerListener != null
11792                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
11793            return true;
11794        }
11795        return onCapturedPointerEvent(event);
11796    }
11797
11798    /**
11799     * Dispatch a generic motion event.
11800     * <p>
11801     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
11802     * are delivered to the view under the pointer.  All other generic motion events are
11803     * delivered to the focused view.  Hover events are handled specially and are delivered
11804     * to {@link #onHoverEvent(MotionEvent)}.
11805     * </p>
11806     *
11807     * @param event The motion event to be dispatched.
11808     * @return True if the event was handled by the view, false otherwise.
11809     */
11810    public boolean dispatchGenericMotionEvent(MotionEvent event) {
11811        if (mInputEventConsistencyVerifier != null) {
11812            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
11813        }
11814
11815        final int source = event.getSource();
11816        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
11817            final int action = event.getAction();
11818            if (action == MotionEvent.ACTION_HOVER_ENTER
11819                    || action == MotionEvent.ACTION_HOVER_MOVE
11820                    || action == MotionEvent.ACTION_HOVER_EXIT) {
11821                if (dispatchHoverEvent(event)) {
11822                    return true;
11823                }
11824            } else if (dispatchGenericPointerEvent(event)) {
11825                return true;
11826            }
11827        } else if (dispatchGenericFocusedEvent(event)) {
11828            return true;
11829        }
11830
11831        if (dispatchGenericMotionEventInternal(event)) {
11832            return true;
11833        }
11834
11835        if (mInputEventConsistencyVerifier != null) {
11836            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11837        }
11838        return false;
11839    }
11840
11841    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
11842        //noinspection SimplifiableIfStatement
11843        ListenerInfo li = mListenerInfo;
11844        if (li != null && li.mOnGenericMotionListener != null
11845                && (mViewFlags & ENABLED_MASK) == ENABLED
11846                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
11847            return true;
11848        }
11849
11850        if (onGenericMotionEvent(event)) {
11851            return true;
11852        }
11853
11854        final int actionButton = event.getActionButton();
11855        switch (event.getActionMasked()) {
11856            case MotionEvent.ACTION_BUTTON_PRESS:
11857                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
11858                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11859                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11860                    if (performContextClick(event.getX(), event.getY())) {
11861                        mInContextButtonPress = true;
11862                        setPressed(true, event.getX(), event.getY());
11863                        removeTapCallback();
11864                        removeLongPressCallback();
11865                        return true;
11866                    }
11867                }
11868                break;
11869
11870            case MotionEvent.ACTION_BUTTON_RELEASE:
11871                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
11872                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
11873                    mInContextButtonPress = false;
11874                    mIgnoreNextUpEvent = true;
11875                }
11876                break;
11877        }
11878
11879        if (mInputEventConsistencyVerifier != null) {
11880            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
11881        }
11882        return false;
11883    }
11884
11885    /**
11886     * Dispatch a hover event.
11887     * <p>
11888     * Do not call this method directly.
11889     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11890     * </p>
11891     *
11892     * @param event The motion event to be dispatched.
11893     * @return True if the event was handled by the view, false otherwise.
11894     */
11895    protected boolean dispatchHoverEvent(MotionEvent event) {
11896        ListenerInfo li = mListenerInfo;
11897        //noinspection SimplifiableIfStatement
11898        if (li != null && li.mOnHoverListener != null
11899                && (mViewFlags & ENABLED_MASK) == ENABLED
11900                && li.mOnHoverListener.onHover(this, event)) {
11901            return true;
11902        }
11903
11904        return onHoverEvent(event);
11905    }
11906
11907    /**
11908     * Returns true if the view has a child to which it has recently sent
11909     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
11910     * it does not have a hovered child, then it must be the innermost hovered view.
11911     * @hide
11912     */
11913    protected boolean hasHoveredChild() {
11914        return false;
11915    }
11916
11917    /**
11918     * Dispatch a generic motion event to the view under the first pointer.
11919     * <p>
11920     * Do not call this method directly.
11921     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11922     * </p>
11923     *
11924     * @param event The motion event to be dispatched.
11925     * @return True if the event was handled by the view, false otherwise.
11926     */
11927    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
11928        return false;
11929    }
11930
11931    /**
11932     * Dispatch a generic motion event to the currently focused view.
11933     * <p>
11934     * Do not call this method directly.
11935     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
11936     * </p>
11937     *
11938     * @param event The motion event to be dispatched.
11939     * @return True if the event was handled by the view, false otherwise.
11940     */
11941    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
11942        return false;
11943    }
11944
11945    /**
11946     * Dispatch a pointer event.
11947     * <p>
11948     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
11949     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
11950     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
11951     * and should not be expected to handle other pointing device features.
11952     * </p>
11953     *
11954     * @param event The motion event to be dispatched.
11955     * @return True if the event was handled by the view, false otherwise.
11956     * @hide
11957     */
11958    public final boolean dispatchPointerEvent(MotionEvent event) {
11959        if (event.isTouchEvent()) {
11960            return dispatchTouchEvent(event);
11961        } else {
11962            return dispatchGenericMotionEvent(event);
11963        }
11964    }
11965
11966    /**
11967     * Called when the window containing this view gains or loses window focus.
11968     * ViewGroups should override to route to their children.
11969     *
11970     * @param hasFocus True if the window containing this view now has focus,
11971     *        false otherwise.
11972     */
11973    public void dispatchWindowFocusChanged(boolean hasFocus) {
11974        onWindowFocusChanged(hasFocus);
11975    }
11976
11977    /**
11978     * Called when the window containing this view gains or loses focus.  Note
11979     * that this is separate from view focus: to receive key events, both
11980     * your view and its window must have focus.  If a window is displayed
11981     * on top of yours that takes input focus, then your own window will lose
11982     * focus but the view focus will remain unchanged.
11983     *
11984     * @param hasWindowFocus True if the window containing this view now has
11985     *        focus, false otherwise.
11986     */
11987    public void onWindowFocusChanged(boolean hasWindowFocus) {
11988        InputMethodManager imm = InputMethodManager.peekInstance();
11989        if (!hasWindowFocus) {
11990            if (isPressed()) {
11991                setPressed(false);
11992            }
11993            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
11994            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
11995                imm.focusOut(this);
11996            }
11997            removeLongPressCallback();
11998            removeTapCallback();
11999            onFocusLost();
12000        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
12001            imm.focusIn(this);
12002        }
12003
12004        notifyEnterOrExitForAutoFillIfNeeded(hasWindowFocus);
12005
12006        refreshDrawableState();
12007    }
12008
12009    /**
12010     * Returns true if this view is in a window that currently has window focus.
12011     * Note that this is not the same as the view itself having focus.
12012     *
12013     * @return True if this view is in a window that currently has window focus.
12014     */
12015    public boolean hasWindowFocus() {
12016        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
12017    }
12018
12019    /**
12020     * Dispatch a view visibility change down the view hierarchy.
12021     * ViewGroups should override to route to their children.
12022     * @param changedView The view whose visibility changed. Could be 'this' or
12023     * an ancestor view.
12024     * @param visibility The new visibility of changedView: {@link #VISIBLE},
12025     * {@link #INVISIBLE} or {@link #GONE}.
12026     */
12027    protected void dispatchVisibilityChanged(@NonNull View changedView,
12028            @Visibility int visibility) {
12029        onVisibilityChanged(changedView, visibility);
12030    }
12031
12032    /**
12033     * Called when the visibility of the view or an ancestor of the view has
12034     * changed.
12035     *
12036     * @param changedView The view whose visibility changed. May be
12037     *                    {@code this} or an ancestor view.
12038     * @param visibility The new visibility, one of {@link #VISIBLE},
12039     *                   {@link #INVISIBLE} or {@link #GONE}.
12040     */
12041    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
12042    }
12043
12044    /**
12045     * Dispatch a hint about whether this view is displayed. For instance, when
12046     * a View moves out of the screen, it might receives a display hint indicating
12047     * the view is not displayed. Applications should not <em>rely</em> on this hint
12048     * as there is no guarantee that they will receive one.
12049     *
12050     * @param hint A hint about whether or not this view is displayed:
12051     * {@link #VISIBLE} or {@link #INVISIBLE}.
12052     */
12053    public void dispatchDisplayHint(@Visibility int hint) {
12054        onDisplayHint(hint);
12055    }
12056
12057    /**
12058     * Gives this view a hint about whether is displayed or not. For instance, when
12059     * a View moves out of the screen, it might receives a display hint indicating
12060     * the view is not displayed. Applications should not <em>rely</em> on this hint
12061     * as there is no guarantee that they will receive one.
12062     *
12063     * @param hint A hint about whether or not this view is displayed:
12064     * {@link #VISIBLE} or {@link #INVISIBLE}.
12065     */
12066    protected void onDisplayHint(@Visibility int hint) {
12067    }
12068
12069    /**
12070     * Dispatch a window visibility change down the view hierarchy.
12071     * ViewGroups should override to route to their children.
12072     *
12073     * @param visibility The new visibility of the window.
12074     *
12075     * @see #onWindowVisibilityChanged(int)
12076     */
12077    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
12078        onWindowVisibilityChanged(visibility);
12079    }
12080
12081    /**
12082     * Called when the window containing has change its visibility
12083     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
12084     * that this tells you whether or not your window is being made visible
12085     * to the window manager; this does <em>not</em> tell you whether or not
12086     * your window is obscured by other windows on the screen, even if it
12087     * is itself visible.
12088     *
12089     * @param visibility The new visibility of the window.
12090     */
12091    protected void onWindowVisibilityChanged(@Visibility int visibility) {
12092        if (visibility == VISIBLE) {
12093            initialAwakenScrollBars();
12094        }
12095    }
12096
12097    /**
12098     * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
12099     * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
12100     * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
12101     *
12102     * @param isVisible true if this view's visibility to the user is uninterrupted by its
12103     *                  ancestors or by window visibility
12104     * @return true if this view is visible to the user, not counting clipping or overlapping
12105     */
12106    boolean dispatchVisibilityAggregated(boolean isVisible) {
12107        final boolean thisVisible = getVisibility() == VISIBLE;
12108        // If we're not visible but something is telling us we are, ignore it.
12109        if (thisVisible || !isVisible) {
12110            onVisibilityAggregated(isVisible);
12111        }
12112        return thisVisible && isVisible;
12113    }
12114
12115    /**
12116     * Called when the user-visibility of this View is potentially affected by a change
12117     * to this view itself, an ancestor view or the window this view is attached to.
12118     *
12119     * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE}
12120     *                  and this view's window is also visible
12121     */
12122    @CallSuper
12123    public void onVisibilityAggregated(boolean isVisible) {
12124        if (isVisible && mAttachInfo != null) {
12125            initialAwakenScrollBars();
12126        }
12127
12128        final Drawable dr = mBackground;
12129        if (dr != null && isVisible != dr.isVisible()) {
12130            dr.setVisible(isVisible, false);
12131        }
12132        final Drawable hl = mDefaultFocusHighlight;
12133        if (hl != null && isVisible != hl.isVisible()) {
12134            hl.setVisible(isVisible, false);
12135        }
12136        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
12137        if (fg != null && isVisible != fg.isVisible()) {
12138            fg.setVisible(isVisible, false);
12139        }
12140
12141        if (isAutofillable()) {
12142            AutofillManager afm = getAutofillManager();
12143
12144            if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) {
12145                if (mVisibilityChangeForAutofillHandler != null) {
12146                    mVisibilityChangeForAutofillHandler.removeMessages(0);
12147                }
12148
12149                // If the view is in the background but still part of the hierarchy this is called
12150                // with isVisible=false. Hence visibility==false requires further checks
12151                if (isVisible) {
12152                    afm.notifyViewVisibilityChange(this, true);
12153                } else {
12154                    if (mVisibilityChangeForAutofillHandler == null) {
12155                        mVisibilityChangeForAutofillHandler =
12156                                new VisibilityChangeForAutofillHandler(afm, this);
12157                    }
12158                    // Let current operation (e.g. removal of the view from the hierarchy)
12159                    // finish before checking state
12160                    mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget();
12161                }
12162            }
12163        }
12164    }
12165
12166    /**
12167     * Returns the current visibility of the window this view is attached to
12168     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
12169     *
12170     * @return Returns the current visibility of the view's window.
12171     */
12172    @Visibility
12173    public int getWindowVisibility() {
12174        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
12175    }
12176
12177    /**
12178     * Retrieve the overall visible display size in which the window this view is
12179     * attached to has been positioned in.  This takes into account screen
12180     * decorations above the window, for both cases where the window itself
12181     * is being position inside of them or the window is being placed under
12182     * then and covered insets are used for the window to position its content
12183     * inside.  In effect, this tells you the available area where content can
12184     * be placed and remain visible to users.
12185     *
12186     * <p>This function requires an IPC back to the window manager to retrieve
12187     * the requested information, so should not be used in performance critical
12188     * code like drawing.
12189     *
12190     * @param outRect Filled in with the visible display frame.  If the view
12191     * is not attached to a window, this is simply the raw display size.
12192     */
12193    public void getWindowVisibleDisplayFrame(Rect outRect) {
12194        if (mAttachInfo != null) {
12195            try {
12196                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12197            } catch (RemoteException e) {
12198                return;
12199            }
12200            // XXX This is really broken, and probably all needs to be done
12201            // in the window manager, and we need to know more about whether
12202            // we want the area behind or in front of the IME.
12203            final Rect insets = mAttachInfo.mVisibleInsets;
12204            outRect.left += insets.left;
12205            outRect.top += insets.top;
12206            outRect.right -= insets.right;
12207            outRect.bottom -= insets.bottom;
12208            return;
12209        }
12210        // The view is not attached to a display so we don't have a context.
12211        // Make a best guess about the display size.
12212        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12213        d.getRectSize(outRect);
12214    }
12215
12216    /**
12217     * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window
12218     * is currently in without any insets.
12219     *
12220     * @hide
12221     */
12222    public void getWindowDisplayFrame(Rect outRect) {
12223        if (mAttachInfo != null) {
12224            try {
12225                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
12226            } catch (RemoteException e) {
12227                return;
12228            }
12229            return;
12230        }
12231        // The view is not attached to a display so we don't have a context.
12232        // Make a best guess about the display size.
12233        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
12234        d.getRectSize(outRect);
12235    }
12236
12237    /**
12238     * Dispatch a notification about a resource configuration change down
12239     * the view hierarchy.
12240     * ViewGroups should override to route to their children.
12241     *
12242     * @param newConfig The new resource configuration.
12243     *
12244     * @see #onConfigurationChanged(android.content.res.Configuration)
12245     */
12246    public void dispatchConfigurationChanged(Configuration newConfig) {
12247        onConfigurationChanged(newConfig);
12248    }
12249
12250    /**
12251     * Called when the current configuration of the resources being used
12252     * by the application have changed.  You can use this to decide when
12253     * to reload resources that can changed based on orientation and other
12254     * configuration characteristics.  You only need to use this if you are
12255     * not relying on the normal {@link android.app.Activity} mechanism of
12256     * recreating the activity instance upon a configuration change.
12257     *
12258     * @param newConfig The new resource configuration.
12259     */
12260    protected void onConfigurationChanged(Configuration newConfig) {
12261    }
12262
12263    /**
12264     * Private function to aggregate all per-view attributes in to the view
12265     * root.
12266     */
12267    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12268        performCollectViewAttributes(attachInfo, visibility);
12269    }
12270
12271    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
12272        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
12273            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
12274                attachInfo.mKeepScreenOn = true;
12275            }
12276            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
12277            ListenerInfo li = mListenerInfo;
12278            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
12279                attachInfo.mHasSystemUiListeners = true;
12280            }
12281        }
12282    }
12283
12284    void needGlobalAttributesUpdate(boolean force) {
12285        final AttachInfo ai = mAttachInfo;
12286        if (ai != null && !ai.mRecomputeGlobalAttributes) {
12287            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
12288                    || ai.mHasSystemUiListeners) {
12289                ai.mRecomputeGlobalAttributes = true;
12290            }
12291        }
12292    }
12293
12294    /**
12295     * Returns whether the device is currently in touch mode.  Touch mode is entered
12296     * once the user begins interacting with the device by touch, and affects various
12297     * things like whether focus is always visible to the user.
12298     *
12299     * @return Whether the device is in touch mode.
12300     */
12301    @ViewDebug.ExportedProperty
12302    public boolean isInTouchMode() {
12303        if (mAttachInfo != null) {
12304            return mAttachInfo.mInTouchMode;
12305        } else {
12306            return ViewRootImpl.isInTouchMode();
12307        }
12308    }
12309
12310    /**
12311     * Returns the context the view is running in, through which it can
12312     * access the current theme, resources, etc.
12313     *
12314     * @return The view's Context.
12315     */
12316    @ViewDebug.CapturedViewProperty
12317    public final Context getContext() {
12318        return mContext;
12319    }
12320
12321    /**
12322     * Handle a key event before it is processed by any input method
12323     * associated with the view hierarchy.  This can be used to intercept
12324     * key events in special situations before the IME consumes them; a
12325     * typical example would be handling the BACK key to update the application's
12326     * UI instead of allowing the IME to see it and close itself.
12327     *
12328     * @param keyCode The value in event.getKeyCode().
12329     * @param event Description of the key event.
12330     * @return If you handled the event, return true. If you want to allow the
12331     *         event to be handled by the next receiver, return false.
12332     */
12333    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
12334        return false;
12335    }
12336
12337    /**
12338     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
12339     * KeyEvent.Callback.onKeyDown()}: perform press of the view
12340     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
12341     * is released, if the view is enabled and clickable.
12342     * <p>
12343     * Key presses in software keyboards will generally NOT trigger this
12344     * listener, although some may elect to do so in some situations. Do not
12345     * rely on this to catch software key presses.
12346     *
12347     * @param keyCode a key code that represents the button pressed, from
12348     *                {@link android.view.KeyEvent}
12349     * @param event the KeyEvent object that defines the button action
12350     */
12351    public boolean onKeyDown(int keyCode, KeyEvent event) {
12352        if (KeyEvent.isConfirmKey(keyCode)) {
12353            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12354                return true;
12355            }
12356
12357            if (event.getRepeatCount() == 0) {
12358                // Long clickable items don't necessarily have to be clickable.
12359                final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE
12360                        || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
12361                if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) {
12362                    // For the purposes of menu anchoring and drawable hotspots,
12363                    // key events are considered to be at the center of the view.
12364                    final float x = getWidth() / 2f;
12365                    final float y = getHeight() / 2f;
12366                    if (clickable) {
12367                        setPressed(true, x, y);
12368                    }
12369                    checkForLongClick(0, x, y);
12370                    return true;
12371                }
12372            }
12373        }
12374
12375        return false;
12376    }
12377
12378    /**
12379     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
12380     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
12381     * the event).
12382     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12383     * although some may elect to do so in some situations. Do not rely on this to
12384     * catch software key presses.
12385     */
12386    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
12387        return false;
12388    }
12389
12390    /**
12391     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
12392     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
12393     * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER}
12394     * or {@link KeyEvent#KEYCODE_SPACE} is released.
12395     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12396     * although some may elect to do so in some situations. Do not rely on this to
12397     * catch software key presses.
12398     *
12399     * @param keyCode A key code that represents the button pressed, from
12400     *                {@link android.view.KeyEvent}.
12401     * @param event   The KeyEvent object that defines the button action.
12402     */
12403    public boolean onKeyUp(int keyCode, KeyEvent event) {
12404        if (KeyEvent.isConfirmKey(keyCode)) {
12405            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
12406                return true;
12407            }
12408            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
12409                setPressed(false);
12410
12411                if (!mHasPerformedLongPress) {
12412                    // This is a tap, so remove the longpress check
12413                    removeLongPressCallback();
12414                    if (!event.isCanceled()) {
12415                        return performClick();
12416                    }
12417                }
12418            }
12419        }
12420        return false;
12421    }
12422
12423    /**
12424     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
12425     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
12426     * the event).
12427     * <p>Key presses in software keyboards will generally NOT trigger this listener,
12428     * although some may elect to do so in some situations. Do not rely on this to
12429     * catch software key presses.
12430     *
12431     * @param keyCode     A key code that represents the button pressed, from
12432     *                    {@link android.view.KeyEvent}.
12433     * @param repeatCount The number of times the action was made.
12434     * @param event       The KeyEvent object that defines the button action.
12435     */
12436    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
12437        return false;
12438    }
12439
12440    /**
12441     * Called on the focused view when a key shortcut event is not handled.
12442     * Override this method to implement local key shortcuts for the View.
12443     * Key shortcuts can also be implemented by setting the
12444     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
12445     *
12446     * @param keyCode The value in event.getKeyCode().
12447     * @param event Description of the key event.
12448     * @return If you handled the event, return true. If you want to allow the
12449     *         event to be handled by the next receiver, return false.
12450     */
12451    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
12452        return false;
12453    }
12454
12455    /**
12456     * Check whether the called view is a text editor, in which case it
12457     * would make sense to automatically display a soft input window for
12458     * it.  Subclasses should override this if they implement
12459     * {@link #onCreateInputConnection(EditorInfo)} to return true if
12460     * a call on that method would return a non-null InputConnection, and
12461     * they are really a first-class editor that the user would normally
12462     * start typing on when the go into a window containing your view.
12463     *
12464     * <p>The default implementation always returns false.  This does
12465     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
12466     * will not be called or the user can not otherwise perform edits on your
12467     * view; it is just a hint to the system that this is not the primary
12468     * purpose of this view.
12469     *
12470     * @return Returns true if this view is a text editor, else false.
12471     */
12472    public boolean onCheckIsTextEditor() {
12473        return false;
12474    }
12475
12476    /**
12477     * Create a new InputConnection for an InputMethod to interact
12478     * with the view.  The default implementation returns null, since it doesn't
12479     * support input methods.  You can override this to implement such support.
12480     * This is only needed for views that take focus and text input.
12481     *
12482     * <p>When implementing this, you probably also want to implement
12483     * {@link #onCheckIsTextEditor()} to indicate you will return a
12484     * non-null InputConnection.</p>
12485     *
12486     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
12487     * object correctly and in its entirety, so that the connected IME can rely
12488     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
12489     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
12490     * must be filled in with the correct cursor position for IMEs to work correctly
12491     * with your application.</p>
12492     *
12493     * @param outAttrs Fill in with attribute information about the connection.
12494     */
12495    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
12496        return null;
12497    }
12498
12499    /**
12500     * Called by the {@link android.view.inputmethod.InputMethodManager}
12501     * when a view who is not the current
12502     * input connection target is trying to make a call on the manager.  The
12503     * default implementation returns false; you can override this to return
12504     * true for certain views if you are performing InputConnection proxying
12505     * to them.
12506     * @param view The View that is making the InputMethodManager call.
12507     * @return Return true to allow the call, false to reject.
12508     */
12509    public boolean checkInputConnectionProxy(View view) {
12510        return false;
12511    }
12512
12513    /**
12514     * Show the context menu for this view. It is not safe to hold on to the
12515     * menu after returning from this method.
12516     *
12517     * You should normally not overload this method. Overload
12518     * {@link #onCreateContextMenu(ContextMenu)} or define an
12519     * {@link OnCreateContextMenuListener} to add items to the context menu.
12520     *
12521     * @param menu The context menu to populate
12522     */
12523    public void createContextMenu(ContextMenu menu) {
12524        ContextMenuInfo menuInfo = getContextMenuInfo();
12525
12526        // Sets the current menu info so all items added to menu will have
12527        // my extra info set.
12528        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
12529
12530        onCreateContextMenu(menu);
12531        ListenerInfo li = mListenerInfo;
12532        if (li != null && li.mOnCreateContextMenuListener != null) {
12533            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
12534        }
12535
12536        // Clear the extra information so subsequent items that aren't mine don't
12537        // have my extra info.
12538        ((MenuBuilder)menu).setCurrentMenuInfo(null);
12539
12540        if (mParent != null) {
12541            mParent.createContextMenu(menu);
12542        }
12543    }
12544
12545    /**
12546     * Views should implement this if they have extra information to associate
12547     * with the context menu. The return result is supplied as a parameter to
12548     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
12549     * callback.
12550     *
12551     * @return Extra information about the item for which the context menu
12552     *         should be shown. This information will vary across different
12553     *         subclasses of View.
12554     */
12555    protected ContextMenuInfo getContextMenuInfo() {
12556        return null;
12557    }
12558
12559    /**
12560     * Views should implement this if the view itself is going to add items to
12561     * the context menu.
12562     *
12563     * @param menu the context menu to populate
12564     */
12565    protected void onCreateContextMenu(ContextMenu menu) {
12566    }
12567
12568    /**
12569     * Implement this method to handle trackball motion events.  The
12570     * <em>relative</em> movement of the trackball since the last event
12571     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
12572     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
12573     * that a movement of 1 corresponds to the user pressing one DPAD key (so
12574     * they will often be fractional values, representing the more fine-grained
12575     * movement information available from a trackball).
12576     *
12577     * @param event The motion event.
12578     * @return True if the event was handled, false otherwise.
12579     */
12580    public boolean onTrackballEvent(MotionEvent event) {
12581        return false;
12582    }
12583
12584    /**
12585     * Implement this method to handle generic motion events.
12586     * <p>
12587     * Generic motion events describe joystick movements, mouse hovers, track pad
12588     * touches, scroll wheel movements and other input events.  The
12589     * {@link MotionEvent#getSource() source} of the motion event specifies
12590     * the class of input that was received.  Implementations of this method
12591     * must examine the bits in the source before processing the event.
12592     * The following code example shows how this is done.
12593     * </p><p>
12594     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
12595     * are delivered to the view under the pointer.  All other generic motion events are
12596     * delivered to the focused view.
12597     * </p>
12598     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
12599     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
12600     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
12601     *             // process the joystick movement...
12602     *             return true;
12603     *         }
12604     *     }
12605     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
12606     *         switch (event.getAction()) {
12607     *             case MotionEvent.ACTION_HOVER_MOVE:
12608     *                 // process the mouse hover movement...
12609     *                 return true;
12610     *             case MotionEvent.ACTION_SCROLL:
12611     *                 // process the scroll wheel movement...
12612     *                 return true;
12613     *         }
12614     *     }
12615     *     return super.onGenericMotionEvent(event);
12616     * }</pre>
12617     *
12618     * @param event The generic motion event being processed.
12619     * @return True if the event was handled, false otherwise.
12620     */
12621    public boolean onGenericMotionEvent(MotionEvent event) {
12622        return false;
12623    }
12624
12625    /**
12626     * Implement this method to handle hover events.
12627     * <p>
12628     * This method is called whenever a pointer is hovering into, over, or out of the
12629     * bounds of a view and the view is not currently being touched.
12630     * Hover events are represented as pointer events with action
12631     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
12632     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
12633     * </p>
12634     * <ul>
12635     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
12636     * when the pointer enters the bounds of the view.</li>
12637     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
12638     * when the pointer has already entered the bounds of the view and has moved.</li>
12639     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
12640     * when the pointer has exited the bounds of the view or when the pointer is
12641     * about to go down due to a button click, tap, or similar user action that
12642     * causes the view to be touched.</li>
12643     * </ul>
12644     * <p>
12645     * The view should implement this method to return true to indicate that it is
12646     * handling the hover event, such as by changing its drawable state.
12647     * </p><p>
12648     * The default implementation calls {@link #setHovered} to update the hovered state
12649     * of the view when a hover enter or hover exit event is received, if the view
12650     * is enabled and is clickable.  The default implementation also sends hover
12651     * accessibility events.
12652     * </p>
12653     *
12654     * @param event The motion event that describes the hover.
12655     * @return True if the view handled the hover event.
12656     *
12657     * @see #isHovered
12658     * @see #setHovered
12659     * @see #onHoverChanged
12660     */
12661    public boolean onHoverEvent(MotionEvent event) {
12662        // The root view may receive hover (or touch) events that are outside the bounds of
12663        // the window.  This code ensures that we only send accessibility events for
12664        // hovers that are actually within the bounds of the root view.
12665        final int action = event.getActionMasked();
12666        if (!mSendingHoverAccessibilityEvents) {
12667            if ((action == MotionEvent.ACTION_HOVER_ENTER
12668                    || action == MotionEvent.ACTION_HOVER_MOVE)
12669                    && !hasHoveredChild()
12670                    && pointInView(event.getX(), event.getY())) {
12671                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
12672                mSendingHoverAccessibilityEvents = true;
12673            }
12674        } else {
12675            if (action == MotionEvent.ACTION_HOVER_EXIT
12676                    || (action == MotionEvent.ACTION_MOVE
12677                            && !pointInView(event.getX(), event.getY()))) {
12678                mSendingHoverAccessibilityEvents = false;
12679                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
12680            }
12681        }
12682
12683        if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE)
12684                && event.isFromSource(InputDevice.SOURCE_MOUSE)
12685                && isOnScrollbar(event.getX(), event.getY())) {
12686            awakenScrollBars();
12687        }
12688
12689        // If we consider ourself hoverable, or if we we're already hovered,
12690        // handle changing state in response to ENTER and EXIT events.
12691        if (isHoverable() || isHovered()) {
12692            switch (action) {
12693                case MotionEvent.ACTION_HOVER_ENTER:
12694                    setHovered(true);
12695                    break;
12696                case MotionEvent.ACTION_HOVER_EXIT:
12697                    setHovered(false);
12698                    break;
12699            }
12700
12701            // Dispatch the event to onGenericMotionEvent before returning true.
12702            // This is to provide compatibility with existing applications that
12703            // handled HOVER_MOVE events in onGenericMotionEvent and that would
12704            // break because of the new default handling for hoverable views
12705            // in onHoverEvent.
12706            // Note that onGenericMotionEvent will be called by default when
12707            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
12708            dispatchGenericMotionEventInternal(event);
12709            // The event was already handled by calling setHovered(), so always
12710            // return true.
12711            return true;
12712        }
12713
12714        return false;
12715    }
12716
12717    /**
12718     * Returns true if the view should handle {@link #onHoverEvent}
12719     * by calling {@link #setHovered} to change its hovered state.
12720     *
12721     * @return True if the view is hoverable.
12722     */
12723    private boolean isHoverable() {
12724        final int viewFlags = mViewFlags;
12725        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12726            return false;
12727        }
12728
12729        return (viewFlags & CLICKABLE) == CLICKABLE
12730                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
12731                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12732    }
12733
12734    /**
12735     * Returns true if the view is currently hovered.
12736     *
12737     * @return True if the view is currently hovered.
12738     *
12739     * @see #setHovered
12740     * @see #onHoverChanged
12741     */
12742    @ViewDebug.ExportedProperty
12743    public boolean isHovered() {
12744        return (mPrivateFlags & PFLAG_HOVERED) != 0;
12745    }
12746
12747    /**
12748     * Sets whether the view is currently hovered.
12749     * <p>
12750     * Calling this method also changes the drawable state of the view.  This
12751     * enables the view to react to hover by using different drawable resources
12752     * to change its appearance.
12753     * </p><p>
12754     * The {@link #onHoverChanged} method is called when the hovered state changes.
12755     * </p>
12756     *
12757     * @param hovered True if the view is hovered.
12758     *
12759     * @see #isHovered
12760     * @see #onHoverChanged
12761     */
12762    public void setHovered(boolean hovered) {
12763        if (hovered) {
12764            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
12765                mPrivateFlags |= PFLAG_HOVERED;
12766                refreshDrawableState();
12767                onHoverChanged(true);
12768            }
12769        } else {
12770            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
12771                mPrivateFlags &= ~PFLAG_HOVERED;
12772                refreshDrawableState();
12773                onHoverChanged(false);
12774            }
12775        }
12776    }
12777
12778    /**
12779     * Implement this method to handle hover state changes.
12780     * <p>
12781     * This method is called whenever the hover state changes as a result of a
12782     * call to {@link #setHovered}.
12783     * </p>
12784     *
12785     * @param hovered The current hover state, as returned by {@link #isHovered}.
12786     *
12787     * @see #isHovered
12788     * @see #setHovered
12789     */
12790    public void onHoverChanged(boolean hovered) {
12791    }
12792
12793    /**
12794     * Handles scroll bar dragging by mouse input.
12795     *
12796     * @hide
12797     * @param event The motion event.
12798     *
12799     * @return true if the event was handled as a scroll bar dragging, false otherwise.
12800     */
12801    protected boolean handleScrollBarDragging(MotionEvent event) {
12802        if (mScrollCache == null) {
12803            return false;
12804        }
12805        final float x = event.getX();
12806        final float y = event.getY();
12807        final int action = event.getAction();
12808        if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING
12809                && action != MotionEvent.ACTION_DOWN)
12810                    || !event.isFromSource(InputDevice.SOURCE_MOUSE)
12811                    || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) {
12812            mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12813            return false;
12814        }
12815
12816        switch (action) {
12817            case MotionEvent.ACTION_MOVE:
12818                if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) {
12819                    return false;
12820                }
12821                if (mScrollCache.mScrollBarDraggingState
12822                        == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) {
12823                    final Rect bounds = mScrollCache.mScrollBarBounds;
12824                    getVerticalScrollBarBounds(bounds, null);
12825                    final int range = computeVerticalScrollRange();
12826                    final int offset = computeVerticalScrollOffset();
12827                    final int extent = computeVerticalScrollExtent();
12828
12829                    final int thumbLength = ScrollBarUtils.getThumbLength(
12830                            bounds.height(), bounds.width(), extent, range);
12831                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12832                            bounds.height(), thumbLength, extent, range, offset);
12833
12834                    final float diff = y - mScrollCache.mScrollBarDraggingPos;
12835                    final float maxThumbOffset = bounds.height() - thumbLength;
12836                    final float newThumbOffset =
12837                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12838                    final int height = getHeight();
12839                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12840                            && height > 0 && extent > 0) {
12841                        final int newY = Math.round((range - extent)
12842                                / ((float)extent / height) * (newThumbOffset / maxThumbOffset));
12843                        if (newY != getScrollY()) {
12844                            mScrollCache.mScrollBarDraggingPos = y;
12845                            setScrollY(newY);
12846                        }
12847                    }
12848                    return true;
12849                }
12850                if (mScrollCache.mScrollBarDraggingState
12851                        == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) {
12852                    final Rect bounds = mScrollCache.mScrollBarBounds;
12853                    getHorizontalScrollBarBounds(bounds, null);
12854                    final int range = computeHorizontalScrollRange();
12855                    final int offset = computeHorizontalScrollOffset();
12856                    final int extent = computeHorizontalScrollExtent();
12857
12858                    final int thumbLength = ScrollBarUtils.getThumbLength(
12859                            bounds.width(), bounds.height(), extent, range);
12860                    final int thumbOffset = ScrollBarUtils.getThumbOffset(
12861                            bounds.width(), thumbLength, extent, range, offset);
12862
12863                    final float diff = x - mScrollCache.mScrollBarDraggingPos;
12864                    final float maxThumbOffset = bounds.width() - thumbLength;
12865                    final float newThumbOffset =
12866                            Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset);
12867                    final int width = getWidth();
12868                    if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0
12869                            && width > 0 && extent > 0) {
12870                        final int newX = Math.round((range - extent)
12871                                / ((float)extent / width) * (newThumbOffset / maxThumbOffset));
12872                        if (newX != getScrollX()) {
12873                            mScrollCache.mScrollBarDraggingPos = x;
12874                            setScrollX(newX);
12875                        }
12876                    }
12877                    return true;
12878                }
12879            case MotionEvent.ACTION_DOWN:
12880                if (mScrollCache.state == ScrollabilityCache.OFF) {
12881                    return false;
12882                }
12883                if (isOnVerticalScrollbarThumb(x, y)) {
12884                    mScrollCache.mScrollBarDraggingState =
12885                            ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR;
12886                    mScrollCache.mScrollBarDraggingPos = y;
12887                    return true;
12888                }
12889                if (isOnHorizontalScrollbarThumb(x, y)) {
12890                    mScrollCache.mScrollBarDraggingState =
12891                            ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR;
12892                    mScrollCache.mScrollBarDraggingPos = x;
12893                    return true;
12894                }
12895        }
12896        mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING;
12897        return false;
12898    }
12899
12900    /**
12901     * Implement this method to handle touch screen motion events.
12902     * <p>
12903     * If this method is used to detect click actions, it is recommended that
12904     * the actions be performed by implementing and calling
12905     * {@link #performClick()}. This will ensure consistent system behavior,
12906     * including:
12907     * <ul>
12908     * <li>obeying click sound preferences
12909     * <li>dispatching OnClickListener calls
12910     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
12911     * accessibility features are enabled
12912     * </ul>
12913     *
12914     * @param event The motion event.
12915     * @return True if the event was handled, false otherwise.
12916     */
12917    public boolean onTouchEvent(MotionEvent event) {
12918        final float x = event.getX();
12919        final float y = event.getY();
12920        final int viewFlags = mViewFlags;
12921        final int action = event.getAction();
12922
12923        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
12924                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
12925                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
12926
12927        if ((viewFlags & ENABLED_MASK) == DISABLED) {
12928            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
12929                setPressed(false);
12930            }
12931            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12932            // A disabled view that is clickable still consumes the touch
12933            // events, it just doesn't respond to them.
12934            return clickable;
12935        }
12936        if (mTouchDelegate != null) {
12937            if (mTouchDelegate.onTouchEvent(event)) {
12938                return true;
12939            }
12940        }
12941
12942        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
12943            switch (action) {
12944                case MotionEvent.ACTION_UP:
12945                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
12946                    if ((viewFlags & TOOLTIP) == TOOLTIP) {
12947                        handleTooltipUp();
12948                    }
12949                    if (!clickable) {
12950                        removeTapCallback();
12951                        removeLongPressCallback();
12952                        mInContextButtonPress = false;
12953                        mHasPerformedLongPress = false;
12954                        mIgnoreNextUpEvent = false;
12955                        break;
12956                    }
12957                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
12958                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
12959                        // take focus if we don't have it already and we should in
12960                        // touch mode.
12961                        boolean focusTaken = false;
12962                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
12963                            focusTaken = requestFocus();
12964                        }
12965
12966                        if (prepressed) {
12967                            // The button is being released before we actually
12968                            // showed it as pressed.  Make it show the pressed
12969                            // state now (before scheduling the click) to ensure
12970                            // the user sees it.
12971                            setPressed(true, x, y);
12972                        }
12973
12974                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
12975                            // This is a tap, so remove the longpress check
12976                            removeLongPressCallback();
12977
12978                            // Only perform take click actions if we were in the pressed state
12979                            if (!focusTaken) {
12980                                // Use a Runnable and post this rather than calling
12981                                // performClick directly. This lets other visual state
12982                                // of the view update before click actions start.
12983                                if (mPerformClick == null) {
12984                                    mPerformClick = new PerformClick();
12985                                }
12986                                if (!post(mPerformClick)) {
12987                                    performClick();
12988                                }
12989                            }
12990                        }
12991
12992                        if (mUnsetPressedState == null) {
12993                            mUnsetPressedState = new UnsetPressedState();
12994                        }
12995
12996                        if (prepressed) {
12997                            postDelayed(mUnsetPressedState,
12998                                    ViewConfiguration.getPressedStateDuration());
12999                        } else if (!post(mUnsetPressedState)) {
13000                            // If the post failed, unpress right now
13001                            mUnsetPressedState.run();
13002                        }
13003
13004                        removeTapCallback();
13005                    }
13006                    mIgnoreNextUpEvent = false;
13007                    break;
13008
13009                case MotionEvent.ACTION_DOWN:
13010                    if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
13011                        mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
13012                    }
13013                    mHasPerformedLongPress = false;
13014
13015                    if (!clickable) {
13016                        checkForLongClick(0, x, y);
13017                        break;
13018                    }
13019
13020                    if (performButtonActionOnTouchDown(event)) {
13021                        break;
13022                    }
13023
13024                    // Walk up the hierarchy to determine if we're inside a scrolling container.
13025                    boolean isInScrollingContainer = isInScrollingContainer();
13026
13027                    // For views inside a scrolling container, delay the pressed feedback for
13028                    // a short period in case this is a scroll.
13029                    if (isInScrollingContainer) {
13030                        mPrivateFlags |= PFLAG_PREPRESSED;
13031                        if (mPendingCheckForTap == null) {
13032                            mPendingCheckForTap = new CheckForTap();
13033                        }
13034                        mPendingCheckForTap.x = event.getX();
13035                        mPendingCheckForTap.y = event.getY();
13036                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
13037                    } else {
13038                        // Not inside a scrolling container, so show the feedback right away
13039                        setPressed(true, x, y);
13040                        checkForLongClick(0, x, y);
13041                    }
13042                    break;
13043
13044                case MotionEvent.ACTION_CANCEL:
13045                    if (clickable) {
13046                        setPressed(false);
13047                    }
13048                    removeTapCallback();
13049                    removeLongPressCallback();
13050                    mInContextButtonPress = false;
13051                    mHasPerformedLongPress = false;
13052                    mIgnoreNextUpEvent = false;
13053                    mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13054                    break;
13055
13056                case MotionEvent.ACTION_MOVE:
13057                    if (clickable) {
13058                        drawableHotspotChanged(x, y);
13059                    }
13060
13061                    // Be lenient about moving outside of buttons
13062                    if (!pointInView(x, y, mTouchSlop)) {
13063                        // Outside button
13064                        // Remove any future long press/tap checks
13065                        removeTapCallback();
13066                        removeLongPressCallback();
13067                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
13068                            setPressed(false);
13069                        }
13070                        mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
13071                    }
13072                    break;
13073            }
13074
13075            return true;
13076        }
13077
13078        return false;
13079    }
13080
13081    /**
13082     * @hide
13083     */
13084    public boolean isInScrollingContainer() {
13085        ViewParent p = getParent();
13086        while (p != null && p instanceof ViewGroup) {
13087            if (((ViewGroup) p).shouldDelayChildPressedState()) {
13088                return true;
13089            }
13090            p = p.getParent();
13091        }
13092        return false;
13093    }
13094
13095    /**
13096     * Remove the longpress detection timer.
13097     */
13098    private void removeLongPressCallback() {
13099        if (mPendingCheckForLongPress != null) {
13100            removeCallbacks(mPendingCheckForLongPress);
13101        }
13102    }
13103
13104    /**
13105     * Remove the pending click action
13106     */
13107    private void removePerformClickCallback() {
13108        if (mPerformClick != null) {
13109            removeCallbacks(mPerformClick);
13110        }
13111    }
13112
13113    /**
13114     * Remove the prepress detection timer.
13115     */
13116    private void removeUnsetPressCallback() {
13117        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
13118            setPressed(false);
13119            removeCallbacks(mUnsetPressedState);
13120        }
13121    }
13122
13123    /**
13124     * Remove the tap detection timer.
13125     */
13126    private void removeTapCallback() {
13127        if (mPendingCheckForTap != null) {
13128            mPrivateFlags &= ~PFLAG_PREPRESSED;
13129            removeCallbacks(mPendingCheckForTap);
13130        }
13131    }
13132
13133    /**
13134     * Cancels a pending long press.  Your subclass can use this if you
13135     * want the context menu to come up if the user presses and holds
13136     * at the same place, but you don't want it to come up if they press
13137     * and then move around enough to cause scrolling.
13138     */
13139    public void cancelLongPress() {
13140        removeLongPressCallback();
13141
13142        /*
13143         * The prepressed state handled by the tap callback is a display
13144         * construct, but the tap callback will post a long press callback
13145         * less its own timeout. Remove it here.
13146         */
13147        removeTapCallback();
13148    }
13149
13150    /**
13151     * Remove the pending callback for sending a
13152     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
13153     */
13154    private void removeSendViewScrolledAccessibilityEventCallback() {
13155        if (mSendViewScrolledAccessibilityEvent != null) {
13156            removeCallbacks(mSendViewScrolledAccessibilityEvent);
13157            mSendViewScrolledAccessibilityEvent.mIsPending = false;
13158        }
13159    }
13160
13161    /**
13162     * Sets the TouchDelegate for this View.
13163     */
13164    public void setTouchDelegate(TouchDelegate delegate) {
13165        mTouchDelegate = delegate;
13166    }
13167
13168    /**
13169     * Gets the TouchDelegate for this View.
13170     */
13171    public TouchDelegate getTouchDelegate() {
13172        return mTouchDelegate;
13173    }
13174
13175    /**
13176     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
13177     *
13178     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
13179     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
13180     * available. This method should only be called for touch events.
13181     *
13182     * <p class="note">This api is not intended for most applications. Buffered dispatch
13183     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
13184     * streams will not improve your input latency. Side effects include: increased latency,
13185     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
13186     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
13187     * you.</p>
13188     */
13189    public final void requestUnbufferedDispatch(MotionEvent event) {
13190        final int action = event.getAction();
13191        if (mAttachInfo == null
13192                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
13193                || !event.isTouchEvent()) {
13194            return;
13195        }
13196        mAttachInfo.mUnbufferedDispatchRequested = true;
13197    }
13198
13199    /**
13200     * Set flags controlling behavior of this view.
13201     *
13202     * @param flags Constant indicating the value which should be set
13203     * @param mask Constant indicating the bit range that should be changed
13204     */
13205    void setFlags(int flags, int mask) {
13206        final boolean accessibilityEnabled =
13207                AccessibilityManager.getInstance(mContext).isEnabled();
13208        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
13209
13210        int old = mViewFlags;
13211        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
13212
13213        int changed = mViewFlags ^ old;
13214        if (changed == 0) {
13215            return;
13216        }
13217        int privateFlags = mPrivateFlags;
13218
13219        // If focusable is auto, update the FOCUSABLE bit.
13220        int focusableChangedByAuto = 0;
13221        if (((mViewFlags & FOCUSABLE_AUTO) != 0)
13222                && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) {
13223            // Heuristic only takes into account whether view is clickable.
13224            final int newFocus;
13225            if ((mViewFlags & CLICKABLE) != 0) {
13226                newFocus = FOCUSABLE;
13227            } else {
13228                newFocus = NOT_FOCUSABLE;
13229            }
13230            mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus;
13231            focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE);
13232            changed = (changed & ~FOCUSABLE) | focusableChangedByAuto;
13233        }
13234
13235        /* Check if the FOCUSABLE bit has changed */
13236        if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) {
13237            if (((old & FOCUSABLE) == FOCUSABLE)
13238                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
13239                /* Give up focus if we are no longer focusable */
13240                clearFocus();
13241            } else if (((old & FOCUSABLE) == NOT_FOCUSABLE)
13242                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
13243                /*
13244                 * Tell the view system that we are now available to take focus
13245                 * if no one else already has it.
13246                 */
13247                if (mParent != null) {
13248                    ViewRootImpl viewRootImpl = getViewRootImpl();
13249                    if (!sAutoFocusableOffUIThreadWontNotifyParents
13250                            || focusableChangedByAuto == 0
13251                            || viewRootImpl == null
13252                            || viewRootImpl.mThread == Thread.currentThread()) {
13253                        mParent.focusableViewAvailable(this);
13254                    }
13255                }
13256            }
13257        }
13258
13259        final int newVisibility = flags & VISIBILITY_MASK;
13260        if (newVisibility == VISIBLE) {
13261            if ((changed & VISIBILITY_MASK) != 0) {
13262                /*
13263                 * If this view is becoming visible, invalidate it in case it changed while
13264                 * it was not visible. Marking it drawn ensures that the invalidation will
13265                 * go through.
13266                 */
13267                mPrivateFlags |= PFLAG_DRAWN;
13268                invalidate(true);
13269
13270                needGlobalAttributesUpdate(true);
13271
13272                // a view becoming visible is worth notifying the parent
13273                // about in case nothing has focus.  even if this specific view
13274                // isn't focusable, it may contain something that is, so let
13275                // the root view try to give this focus if nothing else does.
13276                if ((mParent != null)) {
13277                    mParent.focusableViewAvailable(this);
13278                }
13279            }
13280        }
13281
13282        /* Check if the GONE bit has changed */
13283        if ((changed & GONE) != 0) {
13284            needGlobalAttributesUpdate(false);
13285            requestLayout();
13286
13287            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
13288                if (hasFocus()) clearFocus();
13289                clearAccessibilityFocus();
13290                destroyDrawingCache();
13291                if (mParent instanceof View) {
13292                    // GONE views noop invalidation, so invalidate the parent
13293                    ((View) mParent).invalidate(true);
13294                }
13295                // Mark the view drawn to ensure that it gets invalidated properly the next
13296                // time it is visible and gets invalidated
13297                mPrivateFlags |= PFLAG_DRAWN;
13298            }
13299            if (mAttachInfo != null) {
13300                mAttachInfo.mViewVisibilityChanged = true;
13301            }
13302        }
13303
13304        /* Check if the VISIBLE bit has changed */
13305        if ((changed & INVISIBLE) != 0) {
13306            needGlobalAttributesUpdate(false);
13307            /*
13308             * If this view is becoming invisible, set the DRAWN flag so that
13309             * the next invalidate() will not be skipped.
13310             */
13311            mPrivateFlags |= PFLAG_DRAWN;
13312
13313            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
13314                // root view becoming invisible shouldn't clear focus and accessibility focus
13315                if (getRootView() != this) {
13316                    if (hasFocus()) clearFocus();
13317                    clearAccessibilityFocus();
13318                }
13319            }
13320            if (mAttachInfo != null) {
13321                mAttachInfo.mViewVisibilityChanged = true;
13322            }
13323        }
13324
13325        if ((changed & VISIBILITY_MASK) != 0) {
13326            // If the view is invisible, cleanup its display list to free up resources
13327            if (newVisibility != VISIBLE && mAttachInfo != null) {
13328                cleanupDraw();
13329            }
13330
13331            if (mParent instanceof ViewGroup) {
13332                ((ViewGroup) mParent).onChildVisibilityChanged(this,
13333                        (changed & VISIBILITY_MASK), newVisibility);
13334                ((View) mParent).invalidate(true);
13335            } else if (mParent != null) {
13336                mParent.invalidateChild(this, null);
13337            }
13338
13339            if (mAttachInfo != null) {
13340                dispatchVisibilityChanged(this, newVisibility);
13341
13342                // Aggregated visibility changes are dispatched to attached views
13343                // in visible windows where the parent is currently shown/drawn
13344                // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot),
13345                // discounting clipping or overlapping. This makes it a good place
13346                // to change animation states.
13347                if (mParent != null && getWindowVisibility() == VISIBLE &&
13348                        ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) {
13349                    dispatchVisibilityAggregated(newVisibility == VISIBLE);
13350                }
13351                notifySubtreeAccessibilityStateChangedIfNeeded();
13352            }
13353        }
13354
13355        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
13356            destroyDrawingCache();
13357        }
13358
13359        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
13360            destroyDrawingCache();
13361            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13362            invalidateParentCaches();
13363        }
13364
13365        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
13366            destroyDrawingCache();
13367            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13368        }
13369
13370        if ((changed & DRAW_MASK) != 0) {
13371            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
13372                if (mBackground != null
13373                        || mDefaultFocusHighlight != null
13374                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
13375                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13376                } else {
13377                    mPrivateFlags |= PFLAG_SKIP_DRAW;
13378                }
13379            } else {
13380                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
13381            }
13382            requestLayout();
13383            invalidate(true);
13384        }
13385
13386        if ((changed & KEEP_SCREEN_ON) != 0) {
13387            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13388                mParent.recomputeViewAttributes(this);
13389            }
13390        }
13391
13392        if (accessibilityEnabled) {
13393            if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0
13394                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
13395                    || (changed & CONTEXT_CLICKABLE) != 0) {
13396                if (oldIncludeForAccessibility != includeForAccessibility()) {
13397                    notifySubtreeAccessibilityStateChangedIfNeeded();
13398                } else {
13399                    notifyViewAccessibilityStateChangedIfNeeded(
13400                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13401                }
13402            } else if ((changed & ENABLED_MASK) != 0) {
13403                notifyViewAccessibilityStateChangedIfNeeded(
13404                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
13405            }
13406        }
13407    }
13408
13409    /**
13410     * Change the view's z order in the tree, so it's on top of other sibling
13411     * views. This ordering change may affect layout, if the parent container
13412     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
13413     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
13414     * method should be followed by calls to {@link #requestLayout()} and
13415     * {@link View#invalidate()} on the view's parent to force the parent to redraw
13416     * with the new child ordering.
13417     *
13418     * @see ViewGroup#bringChildToFront(View)
13419     */
13420    public void bringToFront() {
13421        if (mParent != null) {
13422            mParent.bringChildToFront(this);
13423        }
13424    }
13425
13426    /**
13427     * This is called in response to an internal scroll in this view (i.e., the
13428     * view scrolled its own contents). This is typically as a result of
13429     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
13430     * called.
13431     *
13432     * @param l Current horizontal scroll origin.
13433     * @param t Current vertical scroll origin.
13434     * @param oldl Previous horizontal scroll origin.
13435     * @param oldt Previous vertical scroll origin.
13436     */
13437    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
13438        notifySubtreeAccessibilityStateChangedIfNeeded();
13439
13440        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
13441            postSendViewScrolledAccessibilityEventCallback();
13442        }
13443
13444        mBackgroundSizeChanged = true;
13445        mDefaultFocusHighlightSizeChanged = true;
13446        if (mForegroundInfo != null) {
13447            mForegroundInfo.mBoundsChanged = true;
13448        }
13449
13450        final AttachInfo ai = mAttachInfo;
13451        if (ai != null) {
13452            ai.mViewScrollChanged = true;
13453        }
13454
13455        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
13456            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
13457        }
13458    }
13459
13460    /**
13461     * Interface definition for a callback to be invoked when the scroll
13462     * X or Y positions of a view change.
13463     * <p>
13464     * <b>Note:</b> Some views handle scrolling independently from View and may
13465     * have their own separate listeners for scroll-type events. For example,
13466     * {@link android.widget.ListView ListView} allows clients to register an
13467     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
13468     * to listen for changes in list scroll position.
13469     *
13470     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
13471     */
13472    public interface OnScrollChangeListener {
13473        /**
13474         * Called when the scroll position of a view changes.
13475         *
13476         * @param v The view whose scroll position has changed.
13477         * @param scrollX Current horizontal scroll origin.
13478         * @param scrollY Current vertical scroll origin.
13479         * @param oldScrollX Previous horizontal scroll origin.
13480         * @param oldScrollY Previous vertical scroll origin.
13481         */
13482        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
13483    }
13484
13485    /**
13486     * Interface definition for a callback to be invoked when the layout bounds of a view
13487     * changes due to layout processing.
13488     */
13489    public interface OnLayoutChangeListener {
13490        /**
13491         * Called when the layout bounds of a view changes due to layout processing.
13492         *
13493         * @param v The view whose bounds have changed.
13494         * @param left The new value of the view's left property.
13495         * @param top The new value of the view's top property.
13496         * @param right The new value of the view's right property.
13497         * @param bottom The new value of the view's bottom property.
13498         * @param oldLeft The previous value of the view's left property.
13499         * @param oldTop The previous value of the view's top property.
13500         * @param oldRight The previous value of the view's right property.
13501         * @param oldBottom The previous value of the view's bottom property.
13502         */
13503        void onLayoutChange(View v, int left, int top, int right, int bottom,
13504            int oldLeft, int oldTop, int oldRight, int oldBottom);
13505    }
13506
13507    /**
13508     * This is called during layout when the size of this view has changed. If
13509     * you were just added to the view hierarchy, you're called with the old
13510     * values of 0.
13511     *
13512     * @param w Current width of this view.
13513     * @param h Current height of this view.
13514     * @param oldw Old width of this view.
13515     * @param oldh Old height of this view.
13516     */
13517    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
13518    }
13519
13520    /**
13521     * Called by draw to draw the child views. This may be overridden
13522     * by derived classes to gain control just before its children are drawn
13523     * (but after its own view has been drawn).
13524     * @param canvas the canvas on which to draw the view
13525     */
13526    protected void dispatchDraw(Canvas canvas) {
13527
13528    }
13529
13530    /**
13531     * Gets the parent of this view. Note that the parent is a
13532     * ViewParent and not necessarily a View.
13533     *
13534     * @return Parent of this view.
13535     */
13536    public final ViewParent getParent() {
13537        return mParent;
13538    }
13539
13540    /**
13541     * Set the horizontal scrolled position of your view. This will cause a call to
13542     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13543     * invalidated.
13544     * @param value the x position to scroll to
13545     */
13546    public void setScrollX(int value) {
13547        scrollTo(value, mScrollY);
13548    }
13549
13550    /**
13551     * Set the vertical scrolled position of your view. This will cause a call to
13552     * {@link #onScrollChanged(int, int, int, int)} and the view will be
13553     * invalidated.
13554     * @param value the y position to scroll to
13555     */
13556    public void setScrollY(int value) {
13557        scrollTo(mScrollX, value);
13558    }
13559
13560    /**
13561     * Return the scrolled left position of this view. This is the left edge of
13562     * the displayed part of your view. You do not need to draw any pixels
13563     * farther left, since those are outside of the frame of your view on
13564     * screen.
13565     *
13566     * @return The left edge of the displayed part of your view, in pixels.
13567     */
13568    public final int getScrollX() {
13569        return mScrollX;
13570    }
13571
13572    /**
13573     * Return the scrolled top position of this view. This is the top edge of
13574     * the displayed part of your view. You do not need to draw any pixels above
13575     * it, since those are outside of the frame of your view on screen.
13576     *
13577     * @return The top edge of the displayed part of your view, in pixels.
13578     */
13579    public final int getScrollY() {
13580        return mScrollY;
13581    }
13582
13583    /**
13584     * Return the width of the your view.
13585     *
13586     * @return The width of your view, in pixels.
13587     */
13588    @ViewDebug.ExportedProperty(category = "layout")
13589    public final int getWidth() {
13590        return mRight - mLeft;
13591    }
13592
13593    /**
13594     * Return the height of your view.
13595     *
13596     * @return The height of your view, in pixels.
13597     */
13598    @ViewDebug.ExportedProperty(category = "layout")
13599    public final int getHeight() {
13600        return mBottom - mTop;
13601    }
13602
13603    /**
13604     * Return the visible drawing bounds of your view. Fills in the output
13605     * rectangle with the values from getScrollX(), getScrollY(),
13606     * getWidth(), and getHeight(). These bounds do not account for any
13607     * transformation properties currently set on the view, such as
13608     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
13609     *
13610     * @param outRect The (scrolled) drawing bounds of the view.
13611     */
13612    public void getDrawingRect(Rect outRect) {
13613        outRect.left = mScrollX;
13614        outRect.top = mScrollY;
13615        outRect.right = mScrollX + (mRight - mLeft);
13616        outRect.bottom = mScrollY + (mBottom - mTop);
13617    }
13618
13619    /**
13620     * Like {@link #getMeasuredWidthAndState()}, but only returns the
13621     * raw width component (that is the result is masked by
13622     * {@link #MEASURED_SIZE_MASK}).
13623     *
13624     * @return The raw measured width of this view.
13625     */
13626    public final int getMeasuredWidth() {
13627        return mMeasuredWidth & MEASURED_SIZE_MASK;
13628    }
13629
13630    /**
13631     * Return the full width measurement information for this view as computed
13632     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13633     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13634     * This should be used during measurement and layout calculations only. Use
13635     * {@link #getWidth()} to see how wide a view is after layout.
13636     *
13637     * @return The measured width of this view as a bit mask.
13638     */
13639    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13640            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13641                    name = "MEASURED_STATE_TOO_SMALL"),
13642    })
13643    public final int getMeasuredWidthAndState() {
13644        return mMeasuredWidth;
13645    }
13646
13647    /**
13648     * Like {@link #getMeasuredHeightAndState()}, but only returns the
13649     * raw height component (that is the result is masked by
13650     * {@link #MEASURED_SIZE_MASK}).
13651     *
13652     * @return The raw measured height of this view.
13653     */
13654    public final int getMeasuredHeight() {
13655        return mMeasuredHeight & MEASURED_SIZE_MASK;
13656    }
13657
13658    /**
13659     * Return the full height measurement information for this view as computed
13660     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
13661     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13662     * This should be used during measurement and layout calculations only. Use
13663     * {@link #getHeight()} to see how wide a view is after layout.
13664     *
13665     * @return The measured height of this view as a bit mask.
13666     */
13667    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
13668            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
13669                    name = "MEASURED_STATE_TOO_SMALL"),
13670    })
13671    public final int getMeasuredHeightAndState() {
13672        return mMeasuredHeight;
13673    }
13674
13675    /**
13676     * Return only the state bits of {@link #getMeasuredWidthAndState()}
13677     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
13678     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
13679     * and the height component is at the shifted bits
13680     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
13681     */
13682    public final int getMeasuredState() {
13683        return (mMeasuredWidth&MEASURED_STATE_MASK)
13684                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
13685                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
13686    }
13687
13688    /**
13689     * The transform matrix of this view, which is calculated based on the current
13690     * rotation, scale, and pivot properties.
13691     *
13692     * @see #getRotation()
13693     * @see #getScaleX()
13694     * @see #getScaleY()
13695     * @see #getPivotX()
13696     * @see #getPivotY()
13697     * @return The current transform matrix for the view
13698     */
13699    public Matrix getMatrix() {
13700        ensureTransformationInfo();
13701        final Matrix matrix = mTransformationInfo.mMatrix;
13702        mRenderNode.getMatrix(matrix);
13703        return matrix;
13704    }
13705
13706    /**
13707     * Returns true if the transform matrix is the identity matrix.
13708     * Recomputes the matrix if necessary.
13709     *
13710     * @return True if the transform matrix is the identity matrix, false otherwise.
13711     */
13712    final boolean hasIdentityMatrix() {
13713        return mRenderNode.hasIdentityMatrix();
13714    }
13715
13716    void ensureTransformationInfo() {
13717        if (mTransformationInfo == null) {
13718            mTransformationInfo = new TransformationInfo();
13719        }
13720    }
13721
13722    /**
13723     * Utility method to retrieve the inverse of the current mMatrix property.
13724     * We cache the matrix to avoid recalculating it when transform properties
13725     * have not changed.
13726     *
13727     * @return The inverse of the current matrix of this view.
13728     * @hide
13729     */
13730    public final Matrix getInverseMatrix() {
13731        ensureTransformationInfo();
13732        if (mTransformationInfo.mInverseMatrix == null) {
13733            mTransformationInfo.mInverseMatrix = new Matrix();
13734        }
13735        final Matrix matrix = mTransformationInfo.mInverseMatrix;
13736        mRenderNode.getInverseMatrix(matrix);
13737        return matrix;
13738    }
13739
13740    /**
13741     * Gets the distance along the Z axis from the camera to this view.
13742     *
13743     * @see #setCameraDistance(float)
13744     *
13745     * @return The distance along the Z axis.
13746     */
13747    public float getCameraDistance() {
13748        final float dpi = mResources.getDisplayMetrics().densityDpi;
13749        return -(mRenderNode.getCameraDistance() * dpi);
13750    }
13751
13752    /**
13753     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
13754     * views are drawn) from the camera to this view. The camera's distance
13755     * affects 3D transformations, for instance rotations around the X and Y
13756     * axis. If the rotationX or rotationY properties are changed and this view is
13757     * large (more than half the size of the screen), it is recommended to always
13758     * use a camera distance that's greater than the height (X axis rotation) or
13759     * the width (Y axis rotation) of this view.</p>
13760     *
13761     * <p>The distance of the camera from the view plane can have an affect on the
13762     * perspective distortion of the view when it is rotated around the x or y axis.
13763     * For example, a large distance will result in a large viewing angle, and there
13764     * will not be much perspective distortion of the view as it rotates. A short
13765     * distance may cause much more perspective distortion upon rotation, and can
13766     * also result in some drawing artifacts if the rotated view ends up partially
13767     * behind the camera (which is why the recommendation is to use a distance at
13768     * least as far as the size of the view, if the view is to be rotated.)</p>
13769     *
13770     * <p>The distance is expressed in "depth pixels." The default distance depends
13771     * on the screen density. For instance, on a medium density display, the
13772     * default distance is 1280. On a high density display, the default distance
13773     * is 1920.</p>
13774     *
13775     * <p>If you want to specify a distance that leads to visually consistent
13776     * results across various densities, use the following formula:</p>
13777     * <pre>
13778     * float scale = context.getResources().getDisplayMetrics().density;
13779     * view.setCameraDistance(distance * scale);
13780     * </pre>
13781     *
13782     * <p>The density scale factor of a high density display is 1.5,
13783     * and 1920 = 1280 * 1.5.</p>
13784     *
13785     * @param distance The distance in "depth pixels", if negative the opposite
13786     *        value is used
13787     *
13788     * @see #setRotationX(float)
13789     * @see #setRotationY(float)
13790     */
13791    public void setCameraDistance(float distance) {
13792        final float dpi = mResources.getDisplayMetrics().densityDpi;
13793
13794        invalidateViewProperty(true, false);
13795        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
13796        invalidateViewProperty(false, false);
13797
13798        invalidateParentIfNeededAndWasQuickRejected();
13799    }
13800
13801    /**
13802     * The degrees that the view is rotated around the pivot point.
13803     *
13804     * @see #setRotation(float)
13805     * @see #getPivotX()
13806     * @see #getPivotY()
13807     *
13808     * @return The degrees of rotation.
13809     */
13810    @ViewDebug.ExportedProperty(category = "drawing")
13811    public float getRotation() {
13812        return mRenderNode.getRotation();
13813    }
13814
13815    /**
13816     * Sets the degrees that the view is rotated around the pivot point. Increasing values
13817     * result in clockwise rotation.
13818     *
13819     * @param rotation The degrees of rotation.
13820     *
13821     * @see #getRotation()
13822     * @see #getPivotX()
13823     * @see #getPivotY()
13824     * @see #setRotationX(float)
13825     * @see #setRotationY(float)
13826     *
13827     * @attr ref android.R.styleable#View_rotation
13828     */
13829    public void setRotation(float rotation) {
13830        if (rotation != getRotation()) {
13831            // Double-invalidation is necessary to capture view's old and new areas
13832            invalidateViewProperty(true, false);
13833            mRenderNode.setRotation(rotation);
13834            invalidateViewProperty(false, true);
13835
13836            invalidateParentIfNeededAndWasQuickRejected();
13837            notifySubtreeAccessibilityStateChangedIfNeeded();
13838        }
13839    }
13840
13841    /**
13842     * The degrees that the view is rotated around the vertical axis through the pivot point.
13843     *
13844     * @see #getPivotX()
13845     * @see #getPivotY()
13846     * @see #setRotationY(float)
13847     *
13848     * @return The degrees of Y rotation.
13849     */
13850    @ViewDebug.ExportedProperty(category = "drawing")
13851    public float getRotationY() {
13852        return mRenderNode.getRotationY();
13853    }
13854
13855    /**
13856     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
13857     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
13858     * down the y axis.
13859     *
13860     * When rotating large views, it is recommended to adjust the camera distance
13861     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13862     *
13863     * @param rotationY The degrees of Y rotation.
13864     *
13865     * @see #getRotationY()
13866     * @see #getPivotX()
13867     * @see #getPivotY()
13868     * @see #setRotation(float)
13869     * @see #setRotationX(float)
13870     * @see #setCameraDistance(float)
13871     *
13872     * @attr ref android.R.styleable#View_rotationY
13873     */
13874    public void setRotationY(float rotationY) {
13875        if (rotationY != getRotationY()) {
13876            invalidateViewProperty(true, false);
13877            mRenderNode.setRotationY(rotationY);
13878            invalidateViewProperty(false, true);
13879
13880            invalidateParentIfNeededAndWasQuickRejected();
13881            notifySubtreeAccessibilityStateChangedIfNeeded();
13882        }
13883    }
13884
13885    /**
13886     * The degrees that the view is rotated around the horizontal axis through the pivot point.
13887     *
13888     * @see #getPivotX()
13889     * @see #getPivotY()
13890     * @see #setRotationX(float)
13891     *
13892     * @return The degrees of X rotation.
13893     */
13894    @ViewDebug.ExportedProperty(category = "drawing")
13895    public float getRotationX() {
13896        return mRenderNode.getRotationX();
13897    }
13898
13899    /**
13900     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
13901     * Increasing values result in clockwise rotation from the viewpoint of looking down the
13902     * x axis.
13903     *
13904     * When rotating large views, it is recommended to adjust the camera distance
13905     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
13906     *
13907     * @param rotationX The degrees of X rotation.
13908     *
13909     * @see #getRotationX()
13910     * @see #getPivotX()
13911     * @see #getPivotY()
13912     * @see #setRotation(float)
13913     * @see #setRotationY(float)
13914     * @see #setCameraDistance(float)
13915     *
13916     * @attr ref android.R.styleable#View_rotationX
13917     */
13918    public void setRotationX(float rotationX) {
13919        if (rotationX != getRotationX()) {
13920            invalidateViewProperty(true, false);
13921            mRenderNode.setRotationX(rotationX);
13922            invalidateViewProperty(false, true);
13923
13924            invalidateParentIfNeededAndWasQuickRejected();
13925            notifySubtreeAccessibilityStateChangedIfNeeded();
13926        }
13927    }
13928
13929    /**
13930     * The amount that the view is scaled in x around the pivot point, as a proportion of
13931     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
13932     *
13933     * <p>By default, this is 1.0f.
13934     *
13935     * @see #getPivotX()
13936     * @see #getPivotY()
13937     * @return The scaling factor.
13938     */
13939    @ViewDebug.ExportedProperty(category = "drawing")
13940    public float getScaleX() {
13941        return mRenderNode.getScaleX();
13942    }
13943
13944    /**
13945     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
13946     * the view's unscaled width. A value of 1 means that no scaling is applied.
13947     *
13948     * @param scaleX The scaling factor.
13949     * @see #getPivotX()
13950     * @see #getPivotY()
13951     *
13952     * @attr ref android.R.styleable#View_scaleX
13953     */
13954    public void setScaleX(float scaleX) {
13955        if (scaleX != getScaleX()) {
13956            invalidateViewProperty(true, false);
13957            mRenderNode.setScaleX(scaleX);
13958            invalidateViewProperty(false, true);
13959
13960            invalidateParentIfNeededAndWasQuickRejected();
13961            notifySubtreeAccessibilityStateChangedIfNeeded();
13962        }
13963    }
13964
13965    /**
13966     * The amount that the view is scaled in y around the pivot point, as a proportion of
13967     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
13968     *
13969     * <p>By default, this is 1.0f.
13970     *
13971     * @see #getPivotX()
13972     * @see #getPivotY()
13973     * @return The scaling factor.
13974     */
13975    @ViewDebug.ExportedProperty(category = "drawing")
13976    public float getScaleY() {
13977        return mRenderNode.getScaleY();
13978    }
13979
13980    /**
13981     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
13982     * the view's unscaled width. A value of 1 means that no scaling is applied.
13983     *
13984     * @param scaleY The scaling factor.
13985     * @see #getPivotX()
13986     * @see #getPivotY()
13987     *
13988     * @attr ref android.R.styleable#View_scaleY
13989     */
13990    public void setScaleY(float scaleY) {
13991        if (scaleY != getScaleY()) {
13992            invalidateViewProperty(true, false);
13993            mRenderNode.setScaleY(scaleY);
13994            invalidateViewProperty(false, true);
13995
13996            invalidateParentIfNeededAndWasQuickRejected();
13997            notifySubtreeAccessibilityStateChangedIfNeeded();
13998        }
13999    }
14000
14001    /**
14002     * The x location of the point around which the view is {@link #setRotation(float) rotated}
14003     * and {@link #setScaleX(float) scaled}.
14004     *
14005     * @see #getRotation()
14006     * @see #getScaleX()
14007     * @see #getScaleY()
14008     * @see #getPivotY()
14009     * @return The x location of the pivot point.
14010     *
14011     * @attr ref android.R.styleable#View_transformPivotX
14012     */
14013    @ViewDebug.ExportedProperty(category = "drawing")
14014    public float getPivotX() {
14015        return mRenderNode.getPivotX();
14016    }
14017
14018    /**
14019     * Sets the x location of the point around which the view is
14020     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
14021     * By default, the pivot point is centered on the object.
14022     * Setting this property disables this behavior and causes the view to use only the
14023     * explicitly set pivotX and pivotY values.
14024     *
14025     * @param pivotX The x location of the pivot point.
14026     * @see #getRotation()
14027     * @see #getScaleX()
14028     * @see #getScaleY()
14029     * @see #getPivotY()
14030     *
14031     * @attr ref android.R.styleable#View_transformPivotX
14032     */
14033    public void setPivotX(float pivotX) {
14034        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
14035            invalidateViewProperty(true, false);
14036            mRenderNode.setPivotX(pivotX);
14037            invalidateViewProperty(false, true);
14038
14039            invalidateParentIfNeededAndWasQuickRejected();
14040        }
14041    }
14042
14043    /**
14044     * The y location of the point around which the view is {@link #setRotation(float) rotated}
14045     * and {@link #setScaleY(float) scaled}.
14046     *
14047     * @see #getRotation()
14048     * @see #getScaleX()
14049     * @see #getScaleY()
14050     * @see #getPivotY()
14051     * @return The y location of the pivot point.
14052     *
14053     * @attr ref android.R.styleable#View_transformPivotY
14054     */
14055    @ViewDebug.ExportedProperty(category = "drawing")
14056    public float getPivotY() {
14057        return mRenderNode.getPivotY();
14058    }
14059
14060    /**
14061     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
14062     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
14063     * Setting this property disables this behavior and causes the view to use only the
14064     * explicitly set pivotX and pivotY values.
14065     *
14066     * @param pivotY The y location of the pivot point.
14067     * @see #getRotation()
14068     * @see #getScaleX()
14069     * @see #getScaleY()
14070     * @see #getPivotY()
14071     *
14072     * @attr ref android.R.styleable#View_transformPivotY
14073     */
14074    public void setPivotY(float pivotY) {
14075        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
14076            invalidateViewProperty(true, false);
14077            mRenderNode.setPivotY(pivotY);
14078            invalidateViewProperty(false, true);
14079
14080            invalidateParentIfNeededAndWasQuickRejected();
14081        }
14082    }
14083
14084    /**
14085     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
14086     * completely transparent and 1 means the view is completely opaque.
14087     *
14088     * <p>By default this is 1.0f.
14089     * @return The opacity of the view.
14090     */
14091    @ViewDebug.ExportedProperty(category = "drawing")
14092    public float getAlpha() {
14093        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
14094    }
14095
14096    /**
14097     * Sets the behavior for overlapping rendering for this view (see {@link
14098     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
14099     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
14100     * providing the value which is then used internally. That is, when {@link
14101     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
14102     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
14103     * instead.
14104     *
14105     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
14106     * instead of that returned by {@link #hasOverlappingRendering()}.
14107     *
14108     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
14109     */
14110    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
14111        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
14112        if (hasOverlappingRendering) {
14113            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14114        } else {
14115            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
14116        }
14117    }
14118
14119    /**
14120     * Returns the value for overlapping rendering that is used internally. This is either
14121     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
14122     * the return value of {@link #hasOverlappingRendering()}, otherwise.
14123     *
14124     * @return The value for overlapping rendering being used internally.
14125     */
14126    public final boolean getHasOverlappingRendering() {
14127        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
14128                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
14129                hasOverlappingRendering();
14130    }
14131
14132    /**
14133     * Returns whether this View has content which overlaps.
14134     *
14135     * <p>This function, intended to be overridden by specific View types, is an optimization when
14136     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
14137     * an offscreen buffer and then composited into place, which can be expensive. If the view has
14138     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
14139     * directly. An example of overlapping rendering is a TextView with a background image, such as
14140     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
14141     * ImageView with only the foreground image. The default implementation returns true; subclasses
14142     * should override if they have cases which can be optimized.</p>
14143     *
14144     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
14145     * necessitates that a View return true if it uses the methods internally without passing the
14146     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
14147     *
14148     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
14149     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
14150     *
14151     * @return true if the content in this view might overlap, false otherwise.
14152     */
14153    @ViewDebug.ExportedProperty(category = "drawing")
14154    public boolean hasOverlappingRendering() {
14155        return true;
14156    }
14157
14158    /**
14159     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
14160     * completely transparent and 1 means the view is completely opaque.
14161     *
14162     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
14163     * can have significant performance implications, especially for large views. It is best to use
14164     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
14165     *
14166     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
14167     * strongly recommended for performance reasons to either override
14168     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
14169     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
14170     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
14171     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
14172     * of rendering cost, even for simple or small views. Starting with
14173     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
14174     * applied to the view at the rendering level.</p>
14175     *
14176     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
14177     * responsible for applying the opacity itself.</p>
14178     *
14179     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
14180     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
14181     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
14182     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
14183     *
14184     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
14185     * value will clip a View to its bounds, unless the View returns <code>false</code> from
14186     * {@link #hasOverlappingRendering}.</p>
14187     *
14188     * @param alpha The opacity of the view.
14189     *
14190     * @see #hasOverlappingRendering()
14191     * @see #setLayerType(int, android.graphics.Paint)
14192     *
14193     * @attr ref android.R.styleable#View_alpha
14194     */
14195    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
14196        ensureTransformationInfo();
14197        if (mTransformationInfo.mAlpha != alpha) {
14198            // Report visibility changes, which can affect children, to accessibility
14199            if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) {
14200                notifySubtreeAccessibilityStateChangedIfNeeded();
14201            }
14202            mTransformationInfo.mAlpha = alpha;
14203            if (onSetAlpha((int) (alpha * 255))) {
14204                mPrivateFlags |= PFLAG_ALPHA_SET;
14205                // subclass is handling alpha - don't optimize rendering cache invalidation
14206                invalidateParentCaches();
14207                invalidate(true);
14208            } else {
14209                mPrivateFlags &= ~PFLAG_ALPHA_SET;
14210                invalidateViewProperty(true, false);
14211                mRenderNode.setAlpha(getFinalAlpha());
14212            }
14213        }
14214    }
14215
14216    /**
14217     * Faster version of setAlpha() which performs the same steps except there are
14218     * no calls to invalidate(). The caller of this function should perform proper invalidation
14219     * on the parent and this object. The return value indicates whether the subclass handles
14220     * alpha (the return value for onSetAlpha()).
14221     *
14222     * @param alpha The new value for the alpha property
14223     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
14224     *         the new value for the alpha property is different from the old value
14225     */
14226    boolean setAlphaNoInvalidation(float alpha) {
14227        ensureTransformationInfo();
14228        if (mTransformationInfo.mAlpha != alpha) {
14229            mTransformationInfo.mAlpha = alpha;
14230            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
14231            if (subclassHandlesAlpha) {
14232                mPrivateFlags |= PFLAG_ALPHA_SET;
14233                return true;
14234            } else {
14235                mPrivateFlags &= ~PFLAG_ALPHA_SET;
14236                mRenderNode.setAlpha(getFinalAlpha());
14237            }
14238        }
14239        return false;
14240    }
14241
14242    /**
14243     * This property is hidden and intended only for use by the Fade transition, which
14244     * animates it to produce a visual translucency that does not side-effect (or get
14245     * affected by) the real alpha property. This value is composited with the other
14246     * alpha value (and the AlphaAnimation value, when that is present) to produce
14247     * a final visual translucency result, which is what is passed into the DisplayList.
14248     *
14249     * @hide
14250     */
14251    public void setTransitionAlpha(float alpha) {
14252        ensureTransformationInfo();
14253        if (mTransformationInfo.mTransitionAlpha != alpha) {
14254            mTransformationInfo.mTransitionAlpha = alpha;
14255            mPrivateFlags &= ~PFLAG_ALPHA_SET;
14256            invalidateViewProperty(true, false);
14257            mRenderNode.setAlpha(getFinalAlpha());
14258        }
14259    }
14260
14261    /**
14262     * Calculates the visual alpha of this view, which is a combination of the actual
14263     * alpha value and the transitionAlpha value (if set).
14264     */
14265    private float getFinalAlpha() {
14266        if (mTransformationInfo != null) {
14267            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
14268        }
14269        return 1;
14270    }
14271
14272    /**
14273     * This property is hidden and intended only for use by the Fade transition, which
14274     * animates it to produce a visual translucency that does not side-effect (or get
14275     * affected by) the real alpha property. This value is composited with the other
14276     * alpha value (and the AlphaAnimation value, when that is present) to produce
14277     * a final visual translucency result, which is what is passed into the DisplayList.
14278     *
14279     * @hide
14280     */
14281    @ViewDebug.ExportedProperty(category = "drawing")
14282    public float getTransitionAlpha() {
14283        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
14284    }
14285
14286    /**
14287     * Top position of this view relative to its parent.
14288     *
14289     * @return The top of this view, in pixels.
14290     */
14291    @ViewDebug.CapturedViewProperty
14292    public final int getTop() {
14293        return mTop;
14294    }
14295
14296    /**
14297     * Sets the top position of this view relative to its parent. This method is meant to be called
14298     * by the layout system and should not generally be called otherwise, because the property
14299     * may be changed at any time by the layout.
14300     *
14301     * @param top The top of this view, in pixels.
14302     */
14303    public final void setTop(int top) {
14304        if (top != mTop) {
14305            final boolean matrixIsIdentity = hasIdentityMatrix();
14306            if (matrixIsIdentity) {
14307                if (mAttachInfo != null) {
14308                    int minTop;
14309                    int yLoc;
14310                    if (top < mTop) {
14311                        minTop = top;
14312                        yLoc = top - mTop;
14313                    } else {
14314                        minTop = mTop;
14315                        yLoc = 0;
14316                    }
14317                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
14318                }
14319            } else {
14320                // Double-invalidation is necessary to capture view's old and new areas
14321                invalidate(true);
14322            }
14323
14324            int width = mRight - mLeft;
14325            int oldHeight = mBottom - mTop;
14326
14327            mTop = top;
14328            mRenderNode.setTop(mTop);
14329
14330            sizeChange(width, mBottom - mTop, width, oldHeight);
14331
14332            if (!matrixIsIdentity) {
14333                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14334                invalidate(true);
14335            }
14336            mBackgroundSizeChanged = true;
14337            mDefaultFocusHighlightSizeChanged = true;
14338            if (mForegroundInfo != null) {
14339                mForegroundInfo.mBoundsChanged = true;
14340            }
14341            invalidateParentIfNeeded();
14342            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14343                // View was rejected last time it was drawn by its parent; this may have changed
14344                invalidateParentIfNeeded();
14345            }
14346        }
14347    }
14348
14349    /**
14350     * Bottom position of this view relative to its parent.
14351     *
14352     * @return The bottom of this view, in pixels.
14353     */
14354    @ViewDebug.CapturedViewProperty
14355    public final int getBottom() {
14356        return mBottom;
14357    }
14358
14359    /**
14360     * True if this view has changed since the last time being drawn.
14361     *
14362     * @return The dirty state of this view.
14363     */
14364    public boolean isDirty() {
14365        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
14366    }
14367
14368    /**
14369     * Sets the bottom position of this view relative to its parent. This method is meant to be
14370     * called by the layout system and should not generally be called otherwise, because the
14371     * property may be changed at any time by the layout.
14372     *
14373     * @param bottom The bottom of this view, in pixels.
14374     */
14375    public final void setBottom(int bottom) {
14376        if (bottom != mBottom) {
14377            final boolean matrixIsIdentity = hasIdentityMatrix();
14378            if (matrixIsIdentity) {
14379                if (mAttachInfo != null) {
14380                    int maxBottom;
14381                    if (bottom < mBottom) {
14382                        maxBottom = mBottom;
14383                    } else {
14384                        maxBottom = bottom;
14385                    }
14386                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
14387                }
14388            } else {
14389                // Double-invalidation is necessary to capture view's old and new areas
14390                invalidate(true);
14391            }
14392
14393            int width = mRight - mLeft;
14394            int oldHeight = mBottom - mTop;
14395
14396            mBottom = bottom;
14397            mRenderNode.setBottom(mBottom);
14398
14399            sizeChange(width, mBottom - mTop, width, oldHeight);
14400
14401            if (!matrixIsIdentity) {
14402                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14403                invalidate(true);
14404            }
14405            mBackgroundSizeChanged = true;
14406            mDefaultFocusHighlightSizeChanged = true;
14407            if (mForegroundInfo != null) {
14408                mForegroundInfo.mBoundsChanged = true;
14409            }
14410            invalidateParentIfNeeded();
14411            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14412                // View was rejected last time it was drawn by its parent; this may have changed
14413                invalidateParentIfNeeded();
14414            }
14415        }
14416    }
14417
14418    /**
14419     * Left position of this view relative to its parent.
14420     *
14421     * @return The left edge of this view, in pixels.
14422     */
14423    @ViewDebug.CapturedViewProperty
14424    public final int getLeft() {
14425        return mLeft;
14426    }
14427
14428    /**
14429     * Sets the left position of this view relative to its parent. This method is meant to be called
14430     * by the layout system and should not generally be called otherwise, because the property
14431     * may be changed at any time by the layout.
14432     *
14433     * @param left The left of this view, in pixels.
14434     */
14435    public final void setLeft(int left) {
14436        if (left != mLeft) {
14437            final boolean matrixIsIdentity = hasIdentityMatrix();
14438            if (matrixIsIdentity) {
14439                if (mAttachInfo != null) {
14440                    int minLeft;
14441                    int xLoc;
14442                    if (left < mLeft) {
14443                        minLeft = left;
14444                        xLoc = left - mLeft;
14445                    } else {
14446                        minLeft = mLeft;
14447                        xLoc = 0;
14448                    }
14449                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
14450                }
14451            } else {
14452                // Double-invalidation is necessary to capture view's old and new areas
14453                invalidate(true);
14454            }
14455
14456            int oldWidth = mRight - mLeft;
14457            int height = mBottom - mTop;
14458
14459            mLeft = left;
14460            mRenderNode.setLeft(left);
14461
14462            sizeChange(mRight - mLeft, height, oldWidth, height);
14463
14464            if (!matrixIsIdentity) {
14465                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14466                invalidate(true);
14467            }
14468            mBackgroundSizeChanged = true;
14469            mDefaultFocusHighlightSizeChanged = true;
14470            if (mForegroundInfo != null) {
14471                mForegroundInfo.mBoundsChanged = true;
14472            }
14473            invalidateParentIfNeeded();
14474            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14475                // View was rejected last time it was drawn by its parent; this may have changed
14476                invalidateParentIfNeeded();
14477            }
14478        }
14479    }
14480
14481    /**
14482     * Right position of this view relative to its parent.
14483     *
14484     * @return The right edge of this view, in pixels.
14485     */
14486    @ViewDebug.CapturedViewProperty
14487    public final int getRight() {
14488        return mRight;
14489    }
14490
14491    /**
14492     * Sets the right position of this view relative to its parent. This method is meant to be called
14493     * by the layout system and should not generally be called otherwise, because the property
14494     * may be changed at any time by the layout.
14495     *
14496     * @param right The right of this view, in pixels.
14497     */
14498    public final void setRight(int right) {
14499        if (right != mRight) {
14500            final boolean matrixIsIdentity = hasIdentityMatrix();
14501            if (matrixIsIdentity) {
14502                if (mAttachInfo != null) {
14503                    int maxRight;
14504                    if (right < mRight) {
14505                        maxRight = mRight;
14506                    } else {
14507                        maxRight = right;
14508                    }
14509                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
14510                }
14511            } else {
14512                // Double-invalidation is necessary to capture view's old and new areas
14513                invalidate(true);
14514            }
14515
14516            int oldWidth = mRight - mLeft;
14517            int height = mBottom - mTop;
14518
14519            mRight = right;
14520            mRenderNode.setRight(mRight);
14521
14522            sizeChange(mRight - mLeft, height, oldWidth, height);
14523
14524            if (!matrixIsIdentity) {
14525                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
14526                invalidate(true);
14527            }
14528            mBackgroundSizeChanged = true;
14529            mDefaultFocusHighlightSizeChanged = true;
14530            if (mForegroundInfo != null) {
14531                mForegroundInfo.mBoundsChanged = true;
14532            }
14533            invalidateParentIfNeeded();
14534            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
14535                // View was rejected last time it was drawn by its parent; this may have changed
14536                invalidateParentIfNeeded();
14537            }
14538        }
14539    }
14540
14541    /**
14542     * The visual x position of this view, in pixels. This is equivalent to the
14543     * {@link #setTranslationX(float) translationX} property plus the current
14544     * {@link #getLeft() left} property.
14545     *
14546     * @return The visual x position of this view, in pixels.
14547     */
14548    @ViewDebug.ExportedProperty(category = "drawing")
14549    public float getX() {
14550        return mLeft + getTranslationX();
14551    }
14552
14553    /**
14554     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
14555     * {@link #setTranslationX(float) translationX} property to be the difference between
14556     * the x value passed in and the current {@link #getLeft() left} property.
14557     *
14558     * @param x The visual x position of this view, in pixels.
14559     */
14560    public void setX(float x) {
14561        setTranslationX(x - mLeft);
14562    }
14563
14564    /**
14565     * The visual y position of this view, in pixels. This is equivalent to the
14566     * {@link #setTranslationY(float) translationY} property plus the current
14567     * {@link #getTop() top} property.
14568     *
14569     * @return The visual y position of this view, in pixels.
14570     */
14571    @ViewDebug.ExportedProperty(category = "drawing")
14572    public float getY() {
14573        return mTop + getTranslationY();
14574    }
14575
14576    /**
14577     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
14578     * {@link #setTranslationY(float) translationY} property to be the difference between
14579     * the y value passed in and the current {@link #getTop() top} property.
14580     *
14581     * @param y The visual y position of this view, in pixels.
14582     */
14583    public void setY(float y) {
14584        setTranslationY(y - mTop);
14585    }
14586
14587    /**
14588     * The visual z position of this view, in pixels. This is equivalent to the
14589     * {@link #setTranslationZ(float) translationZ} property plus the current
14590     * {@link #getElevation() elevation} property.
14591     *
14592     * @return The visual z position of this view, in pixels.
14593     */
14594    @ViewDebug.ExportedProperty(category = "drawing")
14595    public float getZ() {
14596        return getElevation() + getTranslationZ();
14597    }
14598
14599    /**
14600     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
14601     * {@link #setTranslationZ(float) translationZ} property to be the difference between
14602     * the x value passed in and the current {@link #getElevation() elevation} property.
14603     *
14604     * @param z The visual z position of this view, in pixels.
14605     */
14606    public void setZ(float z) {
14607        setTranslationZ(z - getElevation());
14608    }
14609
14610    /**
14611     * The base elevation of this view relative to its parent, in pixels.
14612     *
14613     * @return The base depth position of the view, in pixels.
14614     */
14615    @ViewDebug.ExportedProperty(category = "drawing")
14616    public float getElevation() {
14617        return mRenderNode.getElevation();
14618    }
14619
14620    /**
14621     * Sets the base elevation of this view, in pixels.
14622     *
14623     * @attr ref android.R.styleable#View_elevation
14624     */
14625    public void setElevation(float elevation) {
14626        if (elevation != getElevation()) {
14627            invalidateViewProperty(true, false);
14628            mRenderNode.setElevation(elevation);
14629            invalidateViewProperty(false, true);
14630
14631            invalidateParentIfNeededAndWasQuickRejected();
14632        }
14633    }
14634
14635    /**
14636     * The horizontal location of this view relative to its {@link #getLeft() left} position.
14637     * This position is post-layout, in addition to wherever the object's
14638     * layout placed it.
14639     *
14640     * @return The horizontal position of this view relative to its left position, in pixels.
14641     */
14642    @ViewDebug.ExportedProperty(category = "drawing")
14643    public float getTranslationX() {
14644        return mRenderNode.getTranslationX();
14645    }
14646
14647    /**
14648     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
14649     * This effectively positions the object post-layout, in addition to wherever the object's
14650     * layout placed it.
14651     *
14652     * @param translationX The horizontal position of this view relative to its left position,
14653     * in pixels.
14654     *
14655     * @attr ref android.R.styleable#View_translationX
14656     */
14657    public void setTranslationX(float translationX) {
14658        if (translationX != getTranslationX()) {
14659            invalidateViewProperty(true, false);
14660            mRenderNode.setTranslationX(translationX);
14661            invalidateViewProperty(false, true);
14662
14663            invalidateParentIfNeededAndWasQuickRejected();
14664            notifySubtreeAccessibilityStateChangedIfNeeded();
14665        }
14666    }
14667
14668    /**
14669     * The vertical location of this view relative to its {@link #getTop() top} position.
14670     * This position is post-layout, in addition to wherever the object's
14671     * layout placed it.
14672     *
14673     * @return The vertical position of this view relative to its top position,
14674     * in pixels.
14675     */
14676    @ViewDebug.ExportedProperty(category = "drawing")
14677    public float getTranslationY() {
14678        return mRenderNode.getTranslationY();
14679    }
14680
14681    /**
14682     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
14683     * This effectively positions the object post-layout, in addition to wherever the object's
14684     * layout placed it.
14685     *
14686     * @param translationY The vertical position of this view relative to its top position,
14687     * in pixels.
14688     *
14689     * @attr ref android.R.styleable#View_translationY
14690     */
14691    public void setTranslationY(float translationY) {
14692        if (translationY != getTranslationY()) {
14693            invalidateViewProperty(true, false);
14694            mRenderNode.setTranslationY(translationY);
14695            invalidateViewProperty(false, true);
14696
14697            invalidateParentIfNeededAndWasQuickRejected();
14698            notifySubtreeAccessibilityStateChangedIfNeeded();
14699        }
14700    }
14701
14702    /**
14703     * The depth location of this view relative to its {@link #getElevation() elevation}.
14704     *
14705     * @return The depth of this view relative to its elevation.
14706     */
14707    @ViewDebug.ExportedProperty(category = "drawing")
14708    public float getTranslationZ() {
14709        return mRenderNode.getTranslationZ();
14710    }
14711
14712    /**
14713     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
14714     *
14715     * @attr ref android.R.styleable#View_translationZ
14716     */
14717    public void setTranslationZ(float translationZ) {
14718        if (translationZ != getTranslationZ()) {
14719            invalidateViewProperty(true, false);
14720            mRenderNode.setTranslationZ(translationZ);
14721            invalidateViewProperty(false, true);
14722
14723            invalidateParentIfNeededAndWasQuickRejected();
14724        }
14725    }
14726
14727    /** @hide */
14728    public void setAnimationMatrix(Matrix matrix) {
14729        invalidateViewProperty(true, false);
14730        mRenderNode.setAnimationMatrix(matrix);
14731        invalidateViewProperty(false, true);
14732
14733        invalidateParentIfNeededAndWasQuickRejected();
14734    }
14735
14736    /**
14737     * Returns the current StateListAnimator if exists.
14738     *
14739     * @return StateListAnimator or null if it does not exists
14740     * @see    #setStateListAnimator(android.animation.StateListAnimator)
14741     */
14742    public StateListAnimator getStateListAnimator() {
14743        return mStateListAnimator;
14744    }
14745
14746    /**
14747     * Attaches the provided StateListAnimator to this View.
14748     * <p>
14749     * Any previously attached StateListAnimator will be detached.
14750     *
14751     * @param stateListAnimator The StateListAnimator to update the view
14752     * @see android.animation.StateListAnimator
14753     */
14754    public void setStateListAnimator(StateListAnimator stateListAnimator) {
14755        if (mStateListAnimator == stateListAnimator) {
14756            return;
14757        }
14758        if (mStateListAnimator != null) {
14759            mStateListAnimator.setTarget(null);
14760        }
14761        mStateListAnimator = stateListAnimator;
14762        if (stateListAnimator != null) {
14763            stateListAnimator.setTarget(this);
14764            if (isAttachedToWindow()) {
14765                stateListAnimator.setState(getDrawableState());
14766            }
14767        }
14768    }
14769
14770    /**
14771     * Returns whether the Outline should be used to clip the contents of the View.
14772     * <p>
14773     * Note that this flag will only be respected if the View's Outline returns true from
14774     * {@link Outline#canClip()}.
14775     *
14776     * @see #setOutlineProvider(ViewOutlineProvider)
14777     * @see #setClipToOutline(boolean)
14778     */
14779    public final boolean getClipToOutline() {
14780        return mRenderNode.getClipToOutline();
14781    }
14782
14783    /**
14784     * Sets whether the View's Outline should be used to clip the contents of the View.
14785     * <p>
14786     * Only a single non-rectangular clip can be applied on a View at any time.
14787     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
14788     * circular reveal} animation take priority over Outline clipping, and
14789     * child Outline clipping takes priority over Outline clipping done by a
14790     * parent.
14791     * <p>
14792     * Note that this flag will only be respected if the View's Outline returns true from
14793     * {@link Outline#canClip()}.
14794     *
14795     * @see #setOutlineProvider(ViewOutlineProvider)
14796     * @see #getClipToOutline()
14797     */
14798    public void setClipToOutline(boolean clipToOutline) {
14799        damageInParent();
14800        if (getClipToOutline() != clipToOutline) {
14801            mRenderNode.setClipToOutline(clipToOutline);
14802        }
14803    }
14804
14805    // correspond to the enum values of View_outlineProvider
14806    private static final int PROVIDER_BACKGROUND = 0;
14807    private static final int PROVIDER_NONE = 1;
14808    private static final int PROVIDER_BOUNDS = 2;
14809    private static final int PROVIDER_PADDED_BOUNDS = 3;
14810    private void setOutlineProviderFromAttribute(int providerInt) {
14811        switch (providerInt) {
14812            case PROVIDER_BACKGROUND:
14813                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
14814                break;
14815            case PROVIDER_NONE:
14816                setOutlineProvider(null);
14817                break;
14818            case PROVIDER_BOUNDS:
14819                setOutlineProvider(ViewOutlineProvider.BOUNDS);
14820                break;
14821            case PROVIDER_PADDED_BOUNDS:
14822                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
14823                break;
14824        }
14825    }
14826
14827    /**
14828     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
14829     * the shape of the shadow it casts, and enables outline clipping.
14830     * <p>
14831     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
14832     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
14833     * outline provider with this method allows this behavior to be overridden.
14834     * <p>
14835     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
14836     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
14837     * <p>
14838     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
14839     *
14840     * @see #setClipToOutline(boolean)
14841     * @see #getClipToOutline()
14842     * @see #getOutlineProvider()
14843     */
14844    public void setOutlineProvider(ViewOutlineProvider provider) {
14845        mOutlineProvider = provider;
14846        invalidateOutline();
14847    }
14848
14849    /**
14850     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
14851     * that defines the shape of the shadow it casts, and enables outline clipping.
14852     *
14853     * @see #setOutlineProvider(ViewOutlineProvider)
14854     */
14855    public ViewOutlineProvider getOutlineProvider() {
14856        return mOutlineProvider;
14857    }
14858
14859    /**
14860     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
14861     *
14862     * @see #setOutlineProvider(ViewOutlineProvider)
14863     */
14864    public void invalidateOutline() {
14865        rebuildOutline();
14866
14867        notifySubtreeAccessibilityStateChangedIfNeeded();
14868        invalidateViewProperty(false, false);
14869    }
14870
14871    /**
14872     * Internal version of {@link #invalidateOutline()} which invalidates the
14873     * outline without invalidating the view itself. This is intended to be called from
14874     * within methods in the View class itself which are the result of the view being
14875     * invalidated already. For example, when we are drawing the background of a View,
14876     * we invalidate the outline in case it changed in the meantime, but we do not
14877     * need to invalidate the view because we're already drawing the background as part
14878     * of drawing the view in response to an earlier invalidation of the view.
14879     */
14880    private void rebuildOutline() {
14881        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
14882        if (mAttachInfo == null) return;
14883
14884        if (mOutlineProvider == null) {
14885            // no provider, remove outline
14886            mRenderNode.setOutline(null);
14887        } else {
14888            final Outline outline = mAttachInfo.mTmpOutline;
14889            outline.setEmpty();
14890            outline.setAlpha(1.0f);
14891
14892            mOutlineProvider.getOutline(this, outline);
14893            mRenderNode.setOutline(outline);
14894        }
14895    }
14896
14897    /**
14898     * HierarchyViewer only
14899     *
14900     * @hide
14901     */
14902    @ViewDebug.ExportedProperty(category = "drawing")
14903    public boolean hasShadow() {
14904        return mRenderNode.hasShadow();
14905    }
14906
14907
14908    /** @hide */
14909    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
14910        mRenderNode.setRevealClip(shouldClip, x, y, radius);
14911        invalidateViewProperty(false, false);
14912    }
14913
14914    /**
14915     * Hit rectangle in parent's coordinates
14916     *
14917     * @param outRect The hit rectangle of the view.
14918     */
14919    public void getHitRect(Rect outRect) {
14920        if (hasIdentityMatrix() || mAttachInfo == null) {
14921            outRect.set(mLeft, mTop, mRight, mBottom);
14922        } else {
14923            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
14924            tmpRect.set(0, 0, getWidth(), getHeight());
14925            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
14926            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
14927                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
14928        }
14929    }
14930
14931    /**
14932     * Determines whether the given point, in local coordinates is inside the view.
14933     */
14934    /*package*/ final boolean pointInView(float localX, float localY) {
14935        return pointInView(localX, localY, 0);
14936    }
14937
14938    /**
14939     * Utility method to determine whether the given point, in local coordinates,
14940     * is inside the view, where the area of the view is expanded by the slop factor.
14941     * This method is called while processing touch-move events to determine if the event
14942     * is still within the view.
14943     *
14944     * @hide
14945     */
14946    public boolean pointInView(float localX, float localY, float slop) {
14947        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
14948                localY < ((mBottom - mTop) + slop);
14949    }
14950
14951    /**
14952     * When a view has focus and the user navigates away from it, the next view is searched for
14953     * starting from the rectangle filled in by this method.
14954     *
14955     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
14956     * of the view.  However, if your view maintains some idea of internal selection,
14957     * such as a cursor, or a selected row or column, you should override this method and
14958     * fill in a more specific rectangle.
14959     *
14960     * @param r The rectangle to fill in, in this view's coordinates.
14961     */
14962    public void getFocusedRect(Rect r) {
14963        getDrawingRect(r);
14964    }
14965
14966    /**
14967     * If some part of this view is not clipped by any of its parents, then
14968     * return that area in r in global (root) coordinates. To convert r to local
14969     * coordinates (without taking possible View rotations into account), offset
14970     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
14971     * If the view is completely clipped or translated out, return false.
14972     *
14973     * @param r If true is returned, r holds the global coordinates of the
14974     *        visible portion of this view.
14975     * @param globalOffset If true is returned, globalOffset holds the dx,dy
14976     *        between this view and its root. globalOffet may be null.
14977     * @return true if r is non-empty (i.e. part of the view is visible at the
14978     *         root level.
14979     */
14980    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
14981        int width = mRight - mLeft;
14982        int height = mBottom - mTop;
14983        if (width > 0 && height > 0) {
14984            r.set(0, 0, width, height);
14985            if (globalOffset != null) {
14986                globalOffset.set(-mScrollX, -mScrollY);
14987            }
14988            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
14989        }
14990        return false;
14991    }
14992
14993    public final boolean getGlobalVisibleRect(Rect r) {
14994        return getGlobalVisibleRect(r, null);
14995    }
14996
14997    public final boolean getLocalVisibleRect(Rect r) {
14998        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
14999        if (getGlobalVisibleRect(r, offset)) {
15000            r.offset(-offset.x, -offset.y); // make r local
15001            return true;
15002        }
15003        return false;
15004    }
15005
15006    /**
15007     * Offset this view's vertical location by the specified number of pixels.
15008     *
15009     * @param offset the number of pixels to offset the view by
15010     */
15011    public void offsetTopAndBottom(int offset) {
15012        if (offset != 0) {
15013            final boolean matrixIsIdentity = hasIdentityMatrix();
15014            if (matrixIsIdentity) {
15015                if (isHardwareAccelerated()) {
15016                    invalidateViewProperty(false, false);
15017                } else {
15018                    final ViewParent p = mParent;
15019                    if (p != null && mAttachInfo != null) {
15020                        final Rect r = mAttachInfo.mTmpInvalRect;
15021                        int minTop;
15022                        int maxBottom;
15023                        int yLoc;
15024                        if (offset < 0) {
15025                            minTop = mTop + offset;
15026                            maxBottom = mBottom;
15027                            yLoc = offset;
15028                        } else {
15029                            minTop = mTop;
15030                            maxBottom = mBottom + offset;
15031                            yLoc = 0;
15032                        }
15033                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
15034                        p.invalidateChild(this, r);
15035                    }
15036                }
15037            } else {
15038                invalidateViewProperty(false, false);
15039            }
15040
15041            mTop += offset;
15042            mBottom += offset;
15043            mRenderNode.offsetTopAndBottom(offset);
15044            if (isHardwareAccelerated()) {
15045                invalidateViewProperty(false, false);
15046                invalidateParentIfNeededAndWasQuickRejected();
15047            } else {
15048                if (!matrixIsIdentity) {
15049                    invalidateViewProperty(false, true);
15050                }
15051                invalidateParentIfNeeded();
15052            }
15053            notifySubtreeAccessibilityStateChangedIfNeeded();
15054        }
15055    }
15056
15057    /**
15058     * Offset this view's horizontal location by the specified amount of pixels.
15059     *
15060     * @param offset the number of pixels to offset the view by
15061     */
15062    public void offsetLeftAndRight(int offset) {
15063        if (offset != 0) {
15064            final boolean matrixIsIdentity = hasIdentityMatrix();
15065            if (matrixIsIdentity) {
15066                if (isHardwareAccelerated()) {
15067                    invalidateViewProperty(false, false);
15068                } else {
15069                    final ViewParent p = mParent;
15070                    if (p != null && mAttachInfo != null) {
15071                        final Rect r = mAttachInfo.mTmpInvalRect;
15072                        int minLeft;
15073                        int maxRight;
15074                        if (offset < 0) {
15075                            minLeft = mLeft + offset;
15076                            maxRight = mRight;
15077                        } else {
15078                            minLeft = mLeft;
15079                            maxRight = mRight + offset;
15080                        }
15081                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
15082                        p.invalidateChild(this, r);
15083                    }
15084                }
15085            } else {
15086                invalidateViewProperty(false, false);
15087            }
15088
15089            mLeft += offset;
15090            mRight += offset;
15091            mRenderNode.offsetLeftAndRight(offset);
15092            if (isHardwareAccelerated()) {
15093                invalidateViewProperty(false, false);
15094                invalidateParentIfNeededAndWasQuickRejected();
15095            } else {
15096                if (!matrixIsIdentity) {
15097                    invalidateViewProperty(false, true);
15098                }
15099                invalidateParentIfNeeded();
15100            }
15101            notifySubtreeAccessibilityStateChangedIfNeeded();
15102        }
15103    }
15104
15105    /**
15106     * Get the LayoutParams associated with this view. All views should have
15107     * layout parameters. These supply parameters to the <i>parent</i> of this
15108     * view specifying how it should be arranged. There are many subclasses of
15109     * ViewGroup.LayoutParams, and these correspond to the different subclasses
15110     * of ViewGroup that are responsible for arranging their children.
15111     *
15112     * This method may return null if this View is not attached to a parent
15113     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
15114     * was not invoked successfully. When a View is attached to a parent
15115     * ViewGroup, this method must not return null.
15116     *
15117     * @return The LayoutParams associated with this view, or null if no
15118     *         parameters have been set yet
15119     */
15120    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
15121    public ViewGroup.LayoutParams getLayoutParams() {
15122        return mLayoutParams;
15123    }
15124
15125    /**
15126     * Set the layout parameters associated with this view. These supply
15127     * parameters to the <i>parent</i> of this view specifying how it should be
15128     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
15129     * correspond to the different subclasses of ViewGroup that are responsible
15130     * for arranging their children.
15131     *
15132     * @param params The layout parameters for this view, cannot be null
15133     */
15134    public void setLayoutParams(ViewGroup.LayoutParams params) {
15135        if (params == null) {
15136            throw new NullPointerException("Layout parameters cannot be null");
15137        }
15138        mLayoutParams = params;
15139        resolveLayoutParams();
15140        if (mParent instanceof ViewGroup) {
15141            ((ViewGroup) mParent).onSetLayoutParams(this, params);
15142        }
15143        requestLayout();
15144    }
15145
15146    /**
15147     * Resolve the layout parameters depending on the resolved layout direction
15148     *
15149     * @hide
15150     */
15151    public void resolveLayoutParams() {
15152        if (mLayoutParams != null) {
15153            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
15154        }
15155    }
15156
15157    /**
15158     * Set the scrolled position of your view. This will cause a call to
15159     * {@link #onScrollChanged(int, int, int, int)} and the view will be
15160     * invalidated.
15161     * @param x the x position to scroll to
15162     * @param y the y position to scroll to
15163     */
15164    public void scrollTo(int x, int y) {
15165        if (mScrollX != x || mScrollY != y) {
15166            int oldX = mScrollX;
15167            int oldY = mScrollY;
15168            mScrollX = x;
15169            mScrollY = y;
15170            invalidateParentCaches();
15171            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
15172            if (!awakenScrollBars()) {
15173                postInvalidateOnAnimation();
15174            }
15175        }
15176    }
15177
15178    /**
15179     * Move the scrolled position of your view. This will cause a call to
15180     * {@link #onScrollChanged(int, int, int, int)} and the view will be
15181     * invalidated.
15182     * @param x the amount of pixels to scroll by horizontally
15183     * @param y the amount of pixels to scroll by vertically
15184     */
15185    public void scrollBy(int x, int y) {
15186        scrollTo(mScrollX + x, mScrollY + y);
15187    }
15188
15189    /**
15190     * <p>Trigger the scrollbars to draw. When invoked this method starts an
15191     * animation to fade the scrollbars out after a default delay. If a subclass
15192     * provides animated scrolling, the start delay should equal the duration
15193     * of the scrolling animation.</p>
15194     *
15195     * <p>The animation starts only if at least one of the scrollbars is
15196     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
15197     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15198     * this method returns true, and false otherwise. If the animation is
15199     * started, this method calls {@link #invalidate()}; in that case the
15200     * caller should not call {@link #invalidate()}.</p>
15201     *
15202     * <p>This method should be invoked every time a subclass directly updates
15203     * the scroll parameters.</p>
15204     *
15205     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
15206     * and {@link #scrollTo(int, int)}.</p>
15207     *
15208     * @return true if the animation is played, false otherwise
15209     *
15210     * @see #awakenScrollBars(int)
15211     * @see #scrollBy(int, int)
15212     * @see #scrollTo(int, int)
15213     * @see #isHorizontalScrollBarEnabled()
15214     * @see #isVerticalScrollBarEnabled()
15215     * @see #setHorizontalScrollBarEnabled(boolean)
15216     * @see #setVerticalScrollBarEnabled(boolean)
15217     */
15218    protected boolean awakenScrollBars() {
15219        return mScrollCache != null &&
15220                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
15221    }
15222
15223    /**
15224     * Trigger the scrollbars to draw.
15225     * This method differs from awakenScrollBars() only in its default duration.
15226     * initialAwakenScrollBars() will show the scroll bars for longer than
15227     * usual to give the user more of a chance to notice them.
15228     *
15229     * @return true if the animation is played, false otherwise.
15230     */
15231    private boolean initialAwakenScrollBars() {
15232        return mScrollCache != null &&
15233                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
15234    }
15235
15236    /**
15237     * <p>
15238     * Trigger the scrollbars to draw. When invoked this method starts an
15239     * animation to fade the scrollbars out after a fixed delay. If a subclass
15240     * provides animated scrolling, the start delay should equal the duration of
15241     * the scrolling animation.
15242     * </p>
15243     *
15244     * <p>
15245     * The animation starts only if at least one of the scrollbars is enabled,
15246     * as specified by {@link #isHorizontalScrollBarEnabled()} and
15247     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15248     * this method returns true, and false otherwise. If the animation is
15249     * started, this method calls {@link #invalidate()}; in that case the caller
15250     * should not call {@link #invalidate()}.
15251     * </p>
15252     *
15253     * <p>
15254     * This method should be invoked every time a subclass directly updates the
15255     * scroll parameters.
15256     * </p>
15257     *
15258     * @param startDelay the delay, in milliseconds, after which the animation
15259     *        should start; when the delay is 0, the animation starts
15260     *        immediately
15261     * @return true if the animation is played, false otherwise
15262     *
15263     * @see #scrollBy(int, int)
15264     * @see #scrollTo(int, int)
15265     * @see #isHorizontalScrollBarEnabled()
15266     * @see #isVerticalScrollBarEnabled()
15267     * @see #setHorizontalScrollBarEnabled(boolean)
15268     * @see #setVerticalScrollBarEnabled(boolean)
15269     */
15270    protected boolean awakenScrollBars(int startDelay) {
15271        return awakenScrollBars(startDelay, true);
15272    }
15273
15274    /**
15275     * <p>
15276     * Trigger the scrollbars to draw. When invoked this method starts an
15277     * animation to fade the scrollbars out after a fixed delay. If a subclass
15278     * provides animated scrolling, the start delay should equal the duration of
15279     * the scrolling animation.
15280     * </p>
15281     *
15282     * <p>
15283     * The animation starts only if at least one of the scrollbars is enabled,
15284     * as specified by {@link #isHorizontalScrollBarEnabled()} and
15285     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
15286     * this method returns true, and false otherwise. If the animation is
15287     * started, this method calls {@link #invalidate()} if the invalidate parameter
15288     * is set to true; in that case the caller
15289     * should not call {@link #invalidate()}.
15290     * </p>
15291     *
15292     * <p>
15293     * This method should be invoked every time a subclass directly updates the
15294     * scroll parameters.
15295     * </p>
15296     *
15297     * @param startDelay the delay, in milliseconds, after which the animation
15298     *        should start; when the delay is 0, the animation starts
15299     *        immediately
15300     *
15301     * @param invalidate Whether this method should call invalidate
15302     *
15303     * @return true if the animation is played, false otherwise
15304     *
15305     * @see #scrollBy(int, int)
15306     * @see #scrollTo(int, int)
15307     * @see #isHorizontalScrollBarEnabled()
15308     * @see #isVerticalScrollBarEnabled()
15309     * @see #setHorizontalScrollBarEnabled(boolean)
15310     * @see #setVerticalScrollBarEnabled(boolean)
15311     */
15312    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
15313        final ScrollabilityCache scrollCache = mScrollCache;
15314
15315        if (scrollCache == null || !scrollCache.fadeScrollBars) {
15316            return false;
15317        }
15318
15319        if (scrollCache.scrollBar == null) {
15320            scrollCache.scrollBar = new ScrollBarDrawable();
15321            scrollCache.scrollBar.setState(getDrawableState());
15322            scrollCache.scrollBar.setCallback(this);
15323        }
15324
15325        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
15326
15327            if (invalidate) {
15328                // Invalidate to show the scrollbars
15329                postInvalidateOnAnimation();
15330            }
15331
15332            if (scrollCache.state == ScrollabilityCache.OFF) {
15333                // FIXME: this is copied from WindowManagerService.
15334                // We should get this value from the system when it
15335                // is possible to do so.
15336                final int KEY_REPEAT_FIRST_DELAY = 750;
15337                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
15338            }
15339
15340            // Tell mScrollCache when we should start fading. This may
15341            // extend the fade start time if one was already scheduled
15342            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
15343            scrollCache.fadeStartTime = fadeStartTime;
15344            scrollCache.state = ScrollabilityCache.ON;
15345
15346            // Schedule our fader to run, unscheduling any old ones first
15347            if (mAttachInfo != null) {
15348                mAttachInfo.mHandler.removeCallbacks(scrollCache);
15349                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
15350            }
15351
15352            return true;
15353        }
15354
15355        return false;
15356    }
15357
15358    /**
15359     * Do not invalidate views which are not visible and which are not running an animation. They
15360     * will not get drawn and they should not set dirty flags as if they will be drawn
15361     */
15362    private boolean skipInvalidate() {
15363        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
15364                (!(mParent instanceof ViewGroup) ||
15365                        !((ViewGroup) mParent).isViewTransitioning(this));
15366    }
15367
15368    /**
15369     * Mark the area defined by dirty as needing to be drawn. If the view is
15370     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15371     * point in the future.
15372     * <p>
15373     * This must be called from a UI thread. To call from a non-UI thread, call
15374     * {@link #postInvalidate()}.
15375     * <p>
15376     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
15377     * {@code dirty}.
15378     *
15379     * @param dirty the rectangle representing the bounds of the dirty region
15380     */
15381    public void invalidate(Rect dirty) {
15382        final int scrollX = mScrollX;
15383        final int scrollY = mScrollY;
15384        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
15385                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
15386    }
15387
15388    /**
15389     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
15390     * coordinates of the dirty rect are relative to the view. If the view is
15391     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
15392     * point in the future.
15393     * <p>
15394     * This must be called from a UI thread. To call from a non-UI thread, call
15395     * {@link #postInvalidate()}.
15396     *
15397     * @param l the left position of the dirty region
15398     * @param t the top position of the dirty region
15399     * @param r the right position of the dirty region
15400     * @param b the bottom position of the dirty region
15401     */
15402    public void invalidate(int l, int t, int r, int b) {
15403        final int scrollX = mScrollX;
15404        final int scrollY = mScrollY;
15405        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
15406    }
15407
15408    /**
15409     * Invalidate the whole view. If the view is visible,
15410     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
15411     * the future.
15412     * <p>
15413     * This must be called from a UI thread. To call from a non-UI thread, call
15414     * {@link #postInvalidate()}.
15415     */
15416    public void invalidate() {
15417        invalidate(true);
15418    }
15419
15420    /**
15421     * This is where the invalidate() work actually happens. A full invalidate()
15422     * causes the drawing cache to be invalidated, but this function can be
15423     * called with invalidateCache set to false to skip that invalidation step
15424     * for cases that do not need it (for example, a component that remains at
15425     * the same dimensions with the same content).
15426     *
15427     * @param invalidateCache Whether the drawing cache for this view should be
15428     *            invalidated as well. This is usually true for a full
15429     *            invalidate, but may be set to false if the View's contents or
15430     *            dimensions have not changed.
15431     * @hide
15432     */
15433    public void invalidate(boolean invalidateCache) {
15434        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
15435    }
15436
15437    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
15438            boolean fullInvalidate) {
15439        if (mGhostView != null) {
15440            mGhostView.invalidate(true);
15441            return;
15442        }
15443
15444        if (skipInvalidate()) {
15445            return;
15446        }
15447
15448        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
15449                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
15450                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
15451                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
15452            if (fullInvalidate) {
15453                mLastIsOpaque = isOpaque();
15454                mPrivateFlags &= ~PFLAG_DRAWN;
15455            }
15456
15457            mPrivateFlags |= PFLAG_DIRTY;
15458
15459            if (invalidateCache) {
15460                mPrivateFlags |= PFLAG_INVALIDATED;
15461                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15462            }
15463
15464            // Propagate the damage rectangle to the parent view.
15465            final AttachInfo ai = mAttachInfo;
15466            final ViewParent p = mParent;
15467            if (p != null && ai != null && l < r && t < b) {
15468                final Rect damage = ai.mTmpInvalRect;
15469                damage.set(l, t, r, b);
15470                p.invalidateChild(this, damage);
15471            }
15472
15473            // Damage the entire projection receiver, if necessary.
15474            if (mBackground != null && mBackground.isProjected()) {
15475                final View receiver = getProjectionReceiver();
15476                if (receiver != null) {
15477                    receiver.damageInParent();
15478                }
15479            }
15480        }
15481    }
15482
15483    /**
15484     * @return this view's projection receiver, or {@code null} if none exists
15485     */
15486    private View getProjectionReceiver() {
15487        ViewParent p = getParent();
15488        while (p != null && p instanceof View) {
15489            final View v = (View) p;
15490            if (v.isProjectionReceiver()) {
15491                return v;
15492            }
15493            p = p.getParent();
15494        }
15495
15496        return null;
15497    }
15498
15499    /**
15500     * @return whether the view is a projection receiver
15501     */
15502    private boolean isProjectionReceiver() {
15503        return mBackground != null;
15504    }
15505
15506    /**
15507     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
15508     * set any flags or handle all of the cases handled by the default invalidation methods.
15509     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
15510     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
15511     * walk up the hierarchy, transforming the dirty rect as necessary.
15512     *
15513     * The method also handles normal invalidation logic if display list properties are not
15514     * being used in this view. The invalidateParent and forceRedraw flags are used by that
15515     * backup approach, to handle these cases used in the various property-setting methods.
15516     *
15517     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
15518     * are not being used in this view
15519     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
15520     * list properties are not being used in this view
15521     */
15522    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
15523        if (!isHardwareAccelerated()
15524                || !mRenderNode.isValid()
15525                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
15526            if (invalidateParent) {
15527                invalidateParentCaches();
15528            }
15529            if (forceRedraw) {
15530                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
15531            }
15532            invalidate(false);
15533        } else {
15534            damageInParent();
15535        }
15536    }
15537
15538    /**
15539     * Tells the parent view to damage this view's bounds.
15540     *
15541     * @hide
15542     */
15543    protected void damageInParent() {
15544        if (mParent != null && mAttachInfo != null) {
15545            mParent.onDescendantInvalidated(this, this);
15546        }
15547    }
15548
15549    /**
15550     * Utility method to transform a given Rect by the current matrix of this view.
15551     */
15552    void transformRect(final Rect rect) {
15553        if (!getMatrix().isIdentity()) {
15554            RectF boundingRect = mAttachInfo.mTmpTransformRect;
15555            boundingRect.set(rect);
15556            getMatrix().mapRect(boundingRect);
15557            rect.set((int) Math.floor(boundingRect.left),
15558                    (int) Math.floor(boundingRect.top),
15559                    (int) Math.ceil(boundingRect.right),
15560                    (int) Math.ceil(boundingRect.bottom));
15561        }
15562    }
15563
15564    /**
15565     * Used to indicate that the parent of this view should clear its caches. This functionality
15566     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15567     * which is necessary when various parent-managed properties of the view change, such as
15568     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
15569     * clears the parent caches and does not causes an invalidate event.
15570     *
15571     * @hide
15572     */
15573    protected void invalidateParentCaches() {
15574        if (mParent instanceof View) {
15575            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
15576        }
15577    }
15578
15579    /**
15580     * Used to indicate that the parent of this view should be invalidated. This functionality
15581     * is used to force the parent to rebuild its display list (when hardware-accelerated),
15582     * which is necessary when various parent-managed properties of the view change, such as
15583     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
15584     * an invalidation event to the parent.
15585     *
15586     * @hide
15587     */
15588    protected void invalidateParentIfNeeded() {
15589        if (isHardwareAccelerated() && mParent instanceof View) {
15590            ((View) mParent).invalidate(true);
15591        }
15592    }
15593
15594    /**
15595     * @hide
15596     */
15597    protected void invalidateParentIfNeededAndWasQuickRejected() {
15598        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
15599            // View was rejected last time it was drawn by its parent; this may have changed
15600            invalidateParentIfNeeded();
15601        }
15602    }
15603
15604    /**
15605     * Indicates whether this View is opaque. An opaque View guarantees that it will
15606     * draw all the pixels overlapping its bounds using a fully opaque color.
15607     *
15608     * Subclasses of View should override this method whenever possible to indicate
15609     * whether an instance is opaque. Opaque Views are treated in a special way by
15610     * the View hierarchy, possibly allowing it to perform optimizations during
15611     * invalidate/draw passes.
15612     *
15613     * @return True if this View is guaranteed to be fully opaque, false otherwise.
15614     */
15615    @ViewDebug.ExportedProperty(category = "drawing")
15616    public boolean isOpaque() {
15617        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
15618                getFinalAlpha() >= 1.0f;
15619    }
15620
15621    /**
15622     * @hide
15623     */
15624    protected void computeOpaqueFlags() {
15625        // Opaque if:
15626        //   - Has a background
15627        //   - Background is opaque
15628        //   - Doesn't have scrollbars or scrollbars overlay
15629
15630        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
15631            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
15632        } else {
15633            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
15634        }
15635
15636        final int flags = mViewFlags;
15637        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
15638                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
15639                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
15640            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
15641        } else {
15642            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
15643        }
15644    }
15645
15646    /**
15647     * @hide
15648     */
15649    protected boolean hasOpaqueScrollbars() {
15650        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
15651    }
15652
15653    /**
15654     * @return A handler associated with the thread running the View. This
15655     * handler can be used to pump events in the UI events queue.
15656     */
15657    public Handler getHandler() {
15658        final AttachInfo attachInfo = mAttachInfo;
15659        if (attachInfo != null) {
15660            return attachInfo.mHandler;
15661        }
15662        return null;
15663    }
15664
15665    /**
15666     * Returns the queue of runnable for this view.
15667     *
15668     * @return the queue of runnables for this view
15669     */
15670    private HandlerActionQueue getRunQueue() {
15671        if (mRunQueue == null) {
15672            mRunQueue = new HandlerActionQueue();
15673        }
15674        return mRunQueue;
15675    }
15676
15677    /**
15678     * Gets the view root associated with the View.
15679     * @return The view root, or null if none.
15680     * @hide
15681     */
15682    public ViewRootImpl getViewRootImpl() {
15683        if (mAttachInfo != null) {
15684            return mAttachInfo.mViewRootImpl;
15685        }
15686        return null;
15687    }
15688
15689    /**
15690     * @hide
15691     */
15692    public ThreadedRenderer getThreadedRenderer() {
15693        return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null;
15694    }
15695
15696    /**
15697     * <p>Causes the Runnable to be added to the message queue.
15698     * The runnable will be run on the user interface thread.</p>
15699     *
15700     * @param action The Runnable that will be executed.
15701     *
15702     * @return Returns true if the Runnable was successfully placed in to the
15703     *         message queue.  Returns false on failure, usually because the
15704     *         looper processing the message queue is exiting.
15705     *
15706     * @see #postDelayed
15707     * @see #removeCallbacks
15708     */
15709    public boolean post(Runnable action) {
15710        final AttachInfo attachInfo = mAttachInfo;
15711        if (attachInfo != null) {
15712            return attachInfo.mHandler.post(action);
15713        }
15714
15715        // Postpone the runnable until we know on which thread it needs to run.
15716        // Assume that the runnable will be successfully placed after attach.
15717        getRunQueue().post(action);
15718        return true;
15719    }
15720
15721    /**
15722     * <p>Causes the Runnable to be added to the message queue, to be run
15723     * after the specified amount of time elapses.
15724     * The runnable will be run on the user interface thread.</p>
15725     *
15726     * @param action The Runnable that will be executed.
15727     * @param delayMillis The delay (in milliseconds) until the Runnable
15728     *        will be executed.
15729     *
15730     * @return true if the Runnable was successfully placed in to the
15731     *         message queue.  Returns false on failure, usually because the
15732     *         looper processing the message queue is exiting.  Note that a
15733     *         result of true does not mean the Runnable will be processed --
15734     *         if the looper is quit before the delivery time of the message
15735     *         occurs then the message will be dropped.
15736     *
15737     * @see #post
15738     * @see #removeCallbacks
15739     */
15740    public boolean postDelayed(Runnable action, long delayMillis) {
15741        final AttachInfo attachInfo = mAttachInfo;
15742        if (attachInfo != null) {
15743            return attachInfo.mHandler.postDelayed(action, delayMillis);
15744        }
15745
15746        // Postpone the runnable until we know on which thread it needs to run.
15747        // Assume that the runnable will be successfully placed after attach.
15748        getRunQueue().postDelayed(action, delayMillis);
15749        return true;
15750    }
15751
15752    /**
15753     * <p>Causes the Runnable to execute on the next animation time step.
15754     * The runnable will be run on the user interface thread.</p>
15755     *
15756     * @param action The Runnable that will be executed.
15757     *
15758     * @see #postOnAnimationDelayed
15759     * @see #removeCallbacks
15760     */
15761    public void postOnAnimation(Runnable action) {
15762        final AttachInfo attachInfo = mAttachInfo;
15763        if (attachInfo != null) {
15764            attachInfo.mViewRootImpl.mChoreographer.postCallback(
15765                    Choreographer.CALLBACK_ANIMATION, action, null);
15766        } else {
15767            // Postpone the runnable until we know
15768            // on which thread it needs to run.
15769            getRunQueue().post(action);
15770        }
15771    }
15772
15773    /**
15774     * <p>Causes the Runnable to execute on the next animation time step,
15775     * after the specified amount of time elapses.
15776     * The runnable will be run on the user interface thread.</p>
15777     *
15778     * @param action The Runnable that will be executed.
15779     * @param delayMillis The delay (in milliseconds) until the Runnable
15780     *        will be executed.
15781     *
15782     * @see #postOnAnimation
15783     * @see #removeCallbacks
15784     */
15785    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
15786        final AttachInfo attachInfo = mAttachInfo;
15787        if (attachInfo != null) {
15788            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15789                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
15790        } else {
15791            // Postpone the runnable until we know
15792            // on which thread it needs to run.
15793            getRunQueue().postDelayed(action, delayMillis);
15794        }
15795    }
15796
15797    /**
15798     * <p>Removes the specified Runnable from the message queue.</p>
15799     *
15800     * @param action The Runnable to remove from the message handling queue
15801     *
15802     * @return true if this view could ask the Handler to remove the Runnable,
15803     *         false otherwise. When the returned value is true, the Runnable
15804     *         may or may not have been actually removed from the message queue
15805     *         (for instance, if the Runnable was not in the queue already.)
15806     *
15807     * @see #post
15808     * @see #postDelayed
15809     * @see #postOnAnimation
15810     * @see #postOnAnimationDelayed
15811     */
15812    public boolean removeCallbacks(Runnable action) {
15813        if (action != null) {
15814            final AttachInfo attachInfo = mAttachInfo;
15815            if (attachInfo != null) {
15816                attachInfo.mHandler.removeCallbacks(action);
15817                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15818                        Choreographer.CALLBACK_ANIMATION, action, null);
15819            }
15820            getRunQueue().removeCallbacks(action);
15821        }
15822        return true;
15823    }
15824
15825    /**
15826     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
15827     * Use this to invalidate the View from a non-UI thread.</p>
15828     *
15829     * <p>This method can be invoked from outside of the UI thread
15830     * only when this View is attached to a window.</p>
15831     *
15832     * @see #invalidate()
15833     * @see #postInvalidateDelayed(long)
15834     */
15835    public void postInvalidate() {
15836        postInvalidateDelayed(0);
15837    }
15838
15839    /**
15840     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15841     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
15842     *
15843     * <p>This method can be invoked from outside of the UI thread
15844     * only when this View is attached to a window.</p>
15845     *
15846     * @param left The left coordinate of the rectangle to invalidate.
15847     * @param top The top coordinate of the rectangle to invalidate.
15848     * @param right The right coordinate of the rectangle to invalidate.
15849     * @param bottom The bottom coordinate of the rectangle to invalidate.
15850     *
15851     * @see #invalidate(int, int, int, int)
15852     * @see #invalidate(Rect)
15853     * @see #postInvalidateDelayed(long, int, int, int, int)
15854     */
15855    public void postInvalidate(int left, int top, int right, int bottom) {
15856        postInvalidateDelayed(0, left, top, right, bottom);
15857    }
15858
15859    /**
15860     * <p>Cause an invalidate to happen on a subsequent cycle through the event
15861     * loop. Waits for the specified amount of time.</p>
15862     *
15863     * <p>This method can be invoked from outside of the UI thread
15864     * only when this View is attached to a window.</p>
15865     *
15866     * @param delayMilliseconds the duration in milliseconds to delay the
15867     *         invalidation by
15868     *
15869     * @see #invalidate()
15870     * @see #postInvalidate()
15871     */
15872    public void postInvalidateDelayed(long delayMilliseconds) {
15873        // We try only with the AttachInfo because there's no point in invalidating
15874        // if we are not attached to our window
15875        final AttachInfo attachInfo = mAttachInfo;
15876        if (attachInfo != null) {
15877            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
15878        }
15879    }
15880
15881    /**
15882     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
15883     * through the event loop. Waits for the specified amount of time.</p>
15884     *
15885     * <p>This method can be invoked from outside of the UI thread
15886     * only when this View is attached to a window.</p>
15887     *
15888     * @param delayMilliseconds the duration in milliseconds to delay the
15889     *         invalidation by
15890     * @param left The left coordinate of the rectangle to invalidate.
15891     * @param top The top coordinate of the rectangle to invalidate.
15892     * @param right The right coordinate of the rectangle to invalidate.
15893     * @param bottom The bottom coordinate of the rectangle to invalidate.
15894     *
15895     * @see #invalidate(int, int, int, int)
15896     * @see #invalidate(Rect)
15897     * @see #postInvalidate(int, int, int, int)
15898     */
15899    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
15900            int right, int bottom) {
15901
15902        // We try only with the AttachInfo because there's no point in invalidating
15903        // if we are not attached to our window
15904        final AttachInfo attachInfo = mAttachInfo;
15905        if (attachInfo != null) {
15906            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15907            info.target = this;
15908            info.left = left;
15909            info.top = top;
15910            info.right = right;
15911            info.bottom = bottom;
15912
15913            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
15914        }
15915    }
15916
15917    /**
15918     * <p>Cause an invalidate to happen on the next animation time step, typically the
15919     * next display frame.</p>
15920     *
15921     * <p>This method can be invoked from outside of the UI thread
15922     * only when this View is attached to a window.</p>
15923     *
15924     * @see #invalidate()
15925     */
15926    public void postInvalidateOnAnimation() {
15927        // We try only with the AttachInfo because there's no point in invalidating
15928        // if we are not attached to our window
15929        final AttachInfo attachInfo = mAttachInfo;
15930        if (attachInfo != null) {
15931            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
15932        }
15933    }
15934
15935    /**
15936     * <p>Cause an invalidate of the specified area to happen on the next animation
15937     * time step, typically the next display frame.</p>
15938     *
15939     * <p>This method can be invoked from outside of the UI thread
15940     * only when this View is attached to a window.</p>
15941     *
15942     * @param left The left coordinate of the rectangle to invalidate.
15943     * @param top The top coordinate of the rectangle to invalidate.
15944     * @param right The right coordinate of the rectangle to invalidate.
15945     * @param bottom The bottom coordinate of the rectangle to invalidate.
15946     *
15947     * @see #invalidate(int, int, int, int)
15948     * @see #invalidate(Rect)
15949     */
15950    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
15951        // We try only with the AttachInfo because there's no point in invalidating
15952        // if we are not attached to our window
15953        final AttachInfo attachInfo = mAttachInfo;
15954        if (attachInfo != null) {
15955            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
15956            info.target = this;
15957            info.left = left;
15958            info.top = top;
15959            info.right = right;
15960            info.bottom = bottom;
15961
15962            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
15963        }
15964    }
15965
15966    /**
15967     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
15968     * This event is sent at most once every
15969     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
15970     */
15971    private void postSendViewScrolledAccessibilityEventCallback() {
15972        if (mSendViewScrolledAccessibilityEvent == null) {
15973            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
15974        }
15975        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
15976            mSendViewScrolledAccessibilityEvent.mIsPending = true;
15977            postDelayed(mSendViewScrolledAccessibilityEvent,
15978                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
15979        }
15980    }
15981
15982    /**
15983     * Called by a parent to request that a child update its values for mScrollX
15984     * and mScrollY if necessary. This will typically be done if the child is
15985     * animating a scroll using a {@link android.widget.Scroller Scroller}
15986     * object.
15987     */
15988    public void computeScroll() {
15989    }
15990
15991    /**
15992     * <p>Indicate whether the horizontal edges are faded when the view is
15993     * scrolled horizontally.</p>
15994     *
15995     * @return true if the horizontal edges should are faded on scroll, false
15996     *         otherwise
15997     *
15998     * @see #setHorizontalFadingEdgeEnabled(boolean)
15999     *
16000     * @attr ref android.R.styleable#View_requiresFadingEdge
16001     */
16002    public boolean isHorizontalFadingEdgeEnabled() {
16003        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
16004    }
16005
16006    /**
16007     * <p>Define whether the horizontal edges should be faded when this view
16008     * is scrolled horizontally.</p>
16009     *
16010     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
16011     *                                    be faded when the view is scrolled
16012     *                                    horizontally
16013     *
16014     * @see #isHorizontalFadingEdgeEnabled()
16015     *
16016     * @attr ref android.R.styleable#View_requiresFadingEdge
16017     */
16018    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
16019        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
16020            if (horizontalFadingEdgeEnabled) {
16021                initScrollCache();
16022            }
16023
16024            mViewFlags ^= FADING_EDGE_HORIZONTAL;
16025        }
16026    }
16027
16028    /**
16029     * <p>Indicate whether the vertical edges are faded when the view is
16030     * scrolled horizontally.</p>
16031     *
16032     * @return true if the vertical edges should are faded on scroll, false
16033     *         otherwise
16034     *
16035     * @see #setVerticalFadingEdgeEnabled(boolean)
16036     *
16037     * @attr ref android.R.styleable#View_requiresFadingEdge
16038     */
16039    public boolean isVerticalFadingEdgeEnabled() {
16040        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
16041    }
16042
16043    /**
16044     * <p>Define whether the vertical edges should be faded when this view
16045     * is scrolled vertically.</p>
16046     *
16047     * @param verticalFadingEdgeEnabled true if the vertical edges should
16048     *                                  be faded when the view is scrolled
16049     *                                  vertically
16050     *
16051     * @see #isVerticalFadingEdgeEnabled()
16052     *
16053     * @attr ref android.R.styleable#View_requiresFadingEdge
16054     */
16055    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
16056        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
16057            if (verticalFadingEdgeEnabled) {
16058                initScrollCache();
16059            }
16060
16061            mViewFlags ^= FADING_EDGE_VERTICAL;
16062        }
16063    }
16064
16065    /**
16066     * Returns the strength, or intensity, of the top faded edge. The strength is
16067     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16068     * returns 0.0 or 1.0 but no value in between.
16069     *
16070     * Subclasses should override this method to provide a smoother fade transition
16071     * when scrolling occurs.
16072     *
16073     * @return the intensity of the top fade as a float between 0.0f and 1.0f
16074     */
16075    protected float getTopFadingEdgeStrength() {
16076        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
16077    }
16078
16079    /**
16080     * Returns the strength, or intensity, of the bottom faded edge. The strength is
16081     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16082     * returns 0.0 or 1.0 but no value in between.
16083     *
16084     * Subclasses should override this method to provide a smoother fade transition
16085     * when scrolling occurs.
16086     *
16087     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
16088     */
16089    protected float getBottomFadingEdgeStrength() {
16090        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
16091                computeVerticalScrollRange() ? 1.0f : 0.0f;
16092    }
16093
16094    /**
16095     * Returns the strength, or intensity, of the left faded edge. The strength is
16096     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16097     * returns 0.0 or 1.0 but no value in between.
16098     *
16099     * Subclasses should override this method to provide a smoother fade transition
16100     * when scrolling occurs.
16101     *
16102     * @return the intensity of the left fade as a float between 0.0f and 1.0f
16103     */
16104    protected float getLeftFadingEdgeStrength() {
16105        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
16106    }
16107
16108    /**
16109     * Returns the strength, or intensity, of the right faded edge. The strength is
16110     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
16111     * returns 0.0 or 1.0 but no value in between.
16112     *
16113     * Subclasses should override this method to provide a smoother fade transition
16114     * when scrolling occurs.
16115     *
16116     * @return the intensity of the right fade as a float between 0.0f and 1.0f
16117     */
16118    protected float getRightFadingEdgeStrength() {
16119        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
16120                computeHorizontalScrollRange() ? 1.0f : 0.0f;
16121    }
16122
16123    /**
16124     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
16125     * scrollbar is not drawn by default.</p>
16126     *
16127     * @return true if the horizontal scrollbar should be painted, false
16128     *         otherwise
16129     *
16130     * @see #setHorizontalScrollBarEnabled(boolean)
16131     */
16132    public boolean isHorizontalScrollBarEnabled() {
16133        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
16134    }
16135
16136    /**
16137     * <p>Define whether the horizontal scrollbar should be drawn or not. The
16138     * scrollbar is not drawn by default.</p>
16139     *
16140     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
16141     *                                   be painted
16142     *
16143     * @see #isHorizontalScrollBarEnabled()
16144     */
16145    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
16146        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
16147            mViewFlags ^= SCROLLBARS_HORIZONTAL;
16148            computeOpaqueFlags();
16149            resolvePadding();
16150        }
16151    }
16152
16153    /**
16154     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
16155     * scrollbar is not drawn by default.</p>
16156     *
16157     * @return true if the vertical scrollbar should be painted, false
16158     *         otherwise
16159     *
16160     * @see #setVerticalScrollBarEnabled(boolean)
16161     */
16162    public boolean isVerticalScrollBarEnabled() {
16163        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
16164    }
16165
16166    /**
16167     * <p>Define whether the vertical scrollbar should be drawn or not. The
16168     * scrollbar is not drawn by default.</p>
16169     *
16170     * @param verticalScrollBarEnabled true if the vertical scrollbar should
16171     *                                 be painted
16172     *
16173     * @see #isVerticalScrollBarEnabled()
16174     */
16175    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
16176        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
16177            mViewFlags ^= SCROLLBARS_VERTICAL;
16178            computeOpaqueFlags();
16179            resolvePadding();
16180        }
16181    }
16182
16183    /**
16184     * @hide
16185     */
16186    protected void recomputePadding() {
16187        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
16188    }
16189
16190    /**
16191     * Define whether scrollbars will fade when the view is not scrolling.
16192     *
16193     * @param fadeScrollbars whether to enable fading
16194     *
16195     * @attr ref android.R.styleable#View_fadeScrollbars
16196     */
16197    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
16198        initScrollCache();
16199        final ScrollabilityCache scrollabilityCache = mScrollCache;
16200        scrollabilityCache.fadeScrollBars = fadeScrollbars;
16201        if (fadeScrollbars) {
16202            scrollabilityCache.state = ScrollabilityCache.OFF;
16203        } else {
16204            scrollabilityCache.state = ScrollabilityCache.ON;
16205        }
16206    }
16207
16208    /**
16209     *
16210     * Returns true if scrollbars will fade when this view is not scrolling
16211     *
16212     * @return true if scrollbar fading is enabled
16213     *
16214     * @attr ref android.R.styleable#View_fadeScrollbars
16215     */
16216    public boolean isScrollbarFadingEnabled() {
16217        return mScrollCache != null && mScrollCache.fadeScrollBars;
16218    }
16219
16220    /**
16221     *
16222     * Returns the delay before scrollbars fade.
16223     *
16224     * @return the delay before scrollbars fade
16225     *
16226     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16227     */
16228    public int getScrollBarDefaultDelayBeforeFade() {
16229        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
16230                mScrollCache.scrollBarDefaultDelayBeforeFade;
16231    }
16232
16233    /**
16234     * Define the delay before scrollbars fade.
16235     *
16236     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
16237     *
16238     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
16239     */
16240    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
16241        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
16242    }
16243
16244    /**
16245     *
16246     * Returns the scrollbar fade duration.
16247     *
16248     * @return the scrollbar fade duration, in milliseconds
16249     *
16250     * @attr ref android.R.styleable#View_scrollbarFadeDuration
16251     */
16252    public int getScrollBarFadeDuration() {
16253        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
16254                mScrollCache.scrollBarFadeDuration;
16255    }
16256
16257    /**
16258     * Define the scrollbar fade duration.
16259     *
16260     * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds
16261     *
16262     * @attr ref android.R.styleable#View_scrollbarFadeDuration
16263     */
16264    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
16265        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
16266    }
16267
16268    /**
16269     *
16270     * Returns the scrollbar size.
16271     *
16272     * @return the scrollbar size
16273     *
16274     * @attr ref android.R.styleable#View_scrollbarSize
16275     */
16276    public int getScrollBarSize() {
16277        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
16278                mScrollCache.scrollBarSize;
16279    }
16280
16281    /**
16282     * Define the scrollbar size.
16283     *
16284     * @param scrollBarSize - the scrollbar size
16285     *
16286     * @attr ref android.R.styleable#View_scrollbarSize
16287     */
16288    public void setScrollBarSize(int scrollBarSize) {
16289        getScrollCache().scrollBarSize = scrollBarSize;
16290    }
16291
16292    /**
16293     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
16294     * inset. When inset, they add to the padding of the view. And the scrollbars
16295     * can be drawn inside the padding area or on the edge of the view. For example,
16296     * if a view has a background drawable and you want to draw the scrollbars
16297     * inside the padding specified by the drawable, you can use
16298     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
16299     * appear at the edge of the view, ignoring the padding, then you can use
16300     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
16301     * @param style the style of the scrollbars. Should be one of
16302     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
16303     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
16304     * @see #SCROLLBARS_INSIDE_OVERLAY
16305     * @see #SCROLLBARS_INSIDE_INSET
16306     * @see #SCROLLBARS_OUTSIDE_OVERLAY
16307     * @see #SCROLLBARS_OUTSIDE_INSET
16308     *
16309     * @attr ref android.R.styleable#View_scrollbarStyle
16310     */
16311    public void setScrollBarStyle(@ScrollBarStyle int style) {
16312        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
16313            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
16314            computeOpaqueFlags();
16315            resolvePadding();
16316        }
16317    }
16318
16319    /**
16320     * <p>Returns the current scrollbar style.</p>
16321     * @return the current scrollbar style
16322     * @see #SCROLLBARS_INSIDE_OVERLAY
16323     * @see #SCROLLBARS_INSIDE_INSET
16324     * @see #SCROLLBARS_OUTSIDE_OVERLAY
16325     * @see #SCROLLBARS_OUTSIDE_INSET
16326     *
16327     * @attr ref android.R.styleable#View_scrollbarStyle
16328     */
16329    @ViewDebug.ExportedProperty(mapping = {
16330            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
16331            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
16332            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
16333            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
16334    })
16335    @ScrollBarStyle
16336    public int getScrollBarStyle() {
16337        return mViewFlags & SCROLLBARS_STYLE_MASK;
16338    }
16339
16340    /**
16341     * <p>Compute the horizontal range that the horizontal scrollbar
16342     * represents.</p>
16343     *
16344     * <p>The range is expressed in arbitrary units that must be the same as the
16345     * units used by {@link #computeHorizontalScrollExtent()} and
16346     * {@link #computeHorizontalScrollOffset()}.</p>
16347     *
16348     * <p>The default range is the drawing width of this view.</p>
16349     *
16350     * @return the total horizontal range represented by the horizontal
16351     *         scrollbar
16352     *
16353     * @see #computeHorizontalScrollExtent()
16354     * @see #computeHorizontalScrollOffset()
16355     * @see android.widget.ScrollBarDrawable
16356     */
16357    protected int computeHorizontalScrollRange() {
16358        return getWidth();
16359    }
16360
16361    /**
16362     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
16363     * within the horizontal range. This value is used to compute the position
16364     * of the thumb within the scrollbar's track.</p>
16365     *
16366     * <p>The range is expressed in arbitrary units that must be the same as the
16367     * units used by {@link #computeHorizontalScrollRange()} and
16368     * {@link #computeHorizontalScrollExtent()}.</p>
16369     *
16370     * <p>The default offset is the scroll offset of this view.</p>
16371     *
16372     * @return the horizontal offset of the scrollbar's thumb
16373     *
16374     * @see #computeHorizontalScrollRange()
16375     * @see #computeHorizontalScrollExtent()
16376     * @see android.widget.ScrollBarDrawable
16377     */
16378    protected int computeHorizontalScrollOffset() {
16379        return mScrollX;
16380    }
16381
16382    /**
16383     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
16384     * within the horizontal range. This value is used to compute the length
16385     * of the thumb within the scrollbar's track.</p>
16386     *
16387     * <p>The range is expressed in arbitrary units that must be the same as the
16388     * units used by {@link #computeHorizontalScrollRange()} and
16389     * {@link #computeHorizontalScrollOffset()}.</p>
16390     *
16391     * <p>The default extent is the drawing width of this view.</p>
16392     *
16393     * @return the horizontal extent of the scrollbar's thumb
16394     *
16395     * @see #computeHorizontalScrollRange()
16396     * @see #computeHorizontalScrollOffset()
16397     * @see android.widget.ScrollBarDrawable
16398     */
16399    protected int computeHorizontalScrollExtent() {
16400        return getWidth();
16401    }
16402
16403    /**
16404     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
16405     *
16406     * <p>The range is expressed in arbitrary units that must be the same as the
16407     * units used by {@link #computeVerticalScrollExtent()} and
16408     * {@link #computeVerticalScrollOffset()}.</p>
16409     *
16410     * @return the total vertical range represented by the vertical scrollbar
16411     *
16412     * <p>The default range is the drawing height of this view.</p>
16413     *
16414     * @see #computeVerticalScrollExtent()
16415     * @see #computeVerticalScrollOffset()
16416     * @see android.widget.ScrollBarDrawable
16417     */
16418    protected int computeVerticalScrollRange() {
16419        return getHeight();
16420    }
16421
16422    /**
16423     * <p>Compute the vertical offset of the vertical scrollbar's thumb
16424     * within the horizontal range. This value is used to compute the position
16425     * of the thumb within the scrollbar's track.</p>
16426     *
16427     * <p>The range is expressed in arbitrary units that must be the same as the
16428     * units used by {@link #computeVerticalScrollRange()} and
16429     * {@link #computeVerticalScrollExtent()}.</p>
16430     *
16431     * <p>The default offset is the scroll offset of this view.</p>
16432     *
16433     * @return the vertical offset of the scrollbar's thumb
16434     *
16435     * @see #computeVerticalScrollRange()
16436     * @see #computeVerticalScrollExtent()
16437     * @see android.widget.ScrollBarDrawable
16438     */
16439    protected int computeVerticalScrollOffset() {
16440        return mScrollY;
16441    }
16442
16443    /**
16444     * <p>Compute the vertical extent of the vertical scrollbar's thumb
16445     * within the vertical range. This value is used to compute the length
16446     * of the thumb within the scrollbar's track.</p>
16447     *
16448     * <p>The range is expressed in arbitrary units that must be the same as the
16449     * units used by {@link #computeVerticalScrollRange()} and
16450     * {@link #computeVerticalScrollOffset()}.</p>
16451     *
16452     * <p>The default extent is the drawing height of this view.</p>
16453     *
16454     * @return the vertical extent of the scrollbar's thumb
16455     *
16456     * @see #computeVerticalScrollRange()
16457     * @see #computeVerticalScrollOffset()
16458     * @see android.widget.ScrollBarDrawable
16459     */
16460    protected int computeVerticalScrollExtent() {
16461        return getHeight();
16462    }
16463
16464    /**
16465     * Check if this view can be scrolled horizontally in a certain direction.
16466     *
16467     * @param direction Negative to check scrolling left, positive to check scrolling right.
16468     * @return true if this view can be scrolled in the specified direction, false otherwise.
16469     */
16470    public boolean canScrollHorizontally(int direction) {
16471        final int offset = computeHorizontalScrollOffset();
16472        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
16473        if (range == 0) return false;
16474        if (direction < 0) {
16475            return offset > 0;
16476        } else {
16477            return offset < range - 1;
16478        }
16479    }
16480
16481    /**
16482     * Check if this view can be scrolled vertically in a certain direction.
16483     *
16484     * @param direction Negative to check scrolling up, positive to check scrolling down.
16485     * @return true if this view can be scrolled in the specified direction, false otherwise.
16486     */
16487    public boolean canScrollVertically(int direction) {
16488        final int offset = computeVerticalScrollOffset();
16489        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
16490        if (range == 0) return false;
16491        if (direction < 0) {
16492            return offset > 0;
16493        } else {
16494            return offset < range - 1;
16495        }
16496    }
16497
16498    void getScrollIndicatorBounds(@NonNull Rect out) {
16499        out.left = mScrollX;
16500        out.right = mScrollX + mRight - mLeft;
16501        out.top = mScrollY;
16502        out.bottom = mScrollY + mBottom - mTop;
16503    }
16504
16505    private void onDrawScrollIndicators(Canvas c) {
16506        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
16507            // No scroll indicators enabled.
16508            return;
16509        }
16510
16511        final Drawable dr = mScrollIndicatorDrawable;
16512        if (dr == null) {
16513            // Scroll indicators aren't supported here.
16514            return;
16515        }
16516
16517        final int h = dr.getIntrinsicHeight();
16518        final int w = dr.getIntrinsicWidth();
16519        final Rect rect = mAttachInfo.mTmpInvalRect;
16520        getScrollIndicatorBounds(rect);
16521
16522        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
16523            final boolean canScrollUp = canScrollVertically(-1);
16524            if (canScrollUp) {
16525                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
16526                dr.draw(c);
16527            }
16528        }
16529
16530        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
16531            final boolean canScrollDown = canScrollVertically(1);
16532            if (canScrollDown) {
16533                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
16534                dr.draw(c);
16535            }
16536        }
16537
16538        final int leftRtl;
16539        final int rightRtl;
16540        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
16541            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
16542            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
16543        } else {
16544            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
16545            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
16546        }
16547
16548        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
16549        if ((mPrivateFlags3 & leftMask) != 0) {
16550            final boolean canScrollLeft = canScrollHorizontally(-1);
16551            if (canScrollLeft) {
16552                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
16553                dr.draw(c);
16554            }
16555        }
16556
16557        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
16558        if ((mPrivateFlags3 & rightMask) != 0) {
16559            final boolean canScrollRight = canScrollHorizontally(1);
16560            if (canScrollRight) {
16561                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
16562                dr.draw(c);
16563            }
16564        }
16565    }
16566
16567    private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds,
16568            @Nullable Rect touchBounds) {
16569        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16570        if (bounds == null) {
16571            return;
16572        }
16573        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16574        final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16575                && !isVerticalScrollBarHidden();
16576        final int size = getHorizontalScrollbarHeight();
16577        final int verticalScrollBarGap = drawVerticalScrollBar ?
16578                getVerticalScrollbarWidth() : 0;
16579        final int width = mRight - mLeft;
16580        final int height = mBottom - mTop;
16581        bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside);
16582        bounds.left = mScrollX + (mPaddingLeft & inside);
16583        bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
16584        bounds.bottom = bounds.top + size;
16585
16586        if (touchBounds == null) {
16587            return;
16588        }
16589        if (touchBounds != bounds) {
16590            touchBounds.set(bounds);
16591        }
16592        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16593        if (touchBounds.height() < minTouchTarget) {
16594            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16595            touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height);
16596            touchBounds.top = touchBounds.bottom - minTouchTarget;
16597        }
16598        if (touchBounds.width() < minTouchTarget) {
16599            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16600            touchBounds.left -= adjust;
16601            touchBounds.right = touchBounds.left + minTouchTarget;
16602        }
16603    }
16604
16605    private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) {
16606        if (mRoundScrollbarRenderer == null) {
16607            getStraightVerticalScrollBarBounds(bounds, touchBounds);
16608        } else {
16609            getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds);
16610        }
16611    }
16612
16613    private void getRoundVerticalScrollBarBounds(Rect bounds) {
16614        final int width = mRight - mLeft;
16615        final int height = mBottom - mTop;
16616        // Do not take padding into account as we always want the scrollbars
16617        // to hug the screen for round wearable devices.
16618        bounds.left = mScrollX;
16619        bounds.top = mScrollY;
16620        bounds.right = bounds.left + width;
16621        bounds.bottom = mScrollY + height;
16622    }
16623
16624    private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds,
16625            @Nullable Rect touchBounds) {
16626        final Rect bounds = drawBounds != null ? drawBounds : touchBounds;
16627        if (bounds == null) {
16628            return;
16629        }
16630        final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
16631        final int size = getVerticalScrollbarWidth();
16632        int verticalScrollbarPosition = mVerticalScrollbarPosition;
16633        if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
16634            verticalScrollbarPosition = isLayoutRtl() ?
16635                    SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
16636        }
16637        final int width = mRight - mLeft;
16638        final int height = mBottom - mTop;
16639        switch (verticalScrollbarPosition) {
16640            default:
16641            case SCROLLBAR_POSITION_RIGHT:
16642                bounds.left = mScrollX + width - size - (mUserPaddingRight & inside);
16643                break;
16644            case SCROLLBAR_POSITION_LEFT:
16645                bounds.left = mScrollX + (mUserPaddingLeft & inside);
16646                break;
16647        }
16648        bounds.top = mScrollY + (mPaddingTop & inside);
16649        bounds.right = bounds.left + size;
16650        bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside);
16651
16652        if (touchBounds == null) {
16653            return;
16654        }
16655        if (touchBounds != bounds) {
16656            touchBounds.set(bounds);
16657        }
16658        final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget;
16659        if (touchBounds.width() < minTouchTarget) {
16660            final int adjust = (minTouchTarget - touchBounds.width()) / 2;
16661            if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) {
16662                touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width);
16663                touchBounds.left = touchBounds.right - minTouchTarget;
16664            } else {
16665                touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX);
16666                touchBounds.right = touchBounds.left + minTouchTarget;
16667            }
16668        }
16669        if (touchBounds.height() < minTouchTarget) {
16670            final int adjust = (minTouchTarget - touchBounds.height()) / 2;
16671            touchBounds.top -= adjust;
16672            touchBounds.bottom = touchBounds.top + minTouchTarget;
16673        }
16674    }
16675
16676    /**
16677     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
16678     * scrollbars are painted only if they have been awakened first.</p>
16679     *
16680     * @param canvas the canvas on which to draw the scrollbars
16681     *
16682     * @see #awakenScrollBars(int)
16683     */
16684    protected final void onDrawScrollBars(Canvas canvas) {
16685        // scrollbars are drawn only when the animation is running
16686        final ScrollabilityCache cache = mScrollCache;
16687
16688        if (cache != null) {
16689
16690            int state = cache.state;
16691
16692            if (state == ScrollabilityCache.OFF) {
16693                return;
16694            }
16695
16696            boolean invalidate = false;
16697
16698            if (state == ScrollabilityCache.FADING) {
16699                // We're fading -- get our fade interpolation
16700                if (cache.interpolatorValues == null) {
16701                    cache.interpolatorValues = new float[1];
16702                }
16703
16704                float[] values = cache.interpolatorValues;
16705
16706                // Stops the animation if we're done
16707                if (cache.scrollBarInterpolator.timeToValues(values) ==
16708                        Interpolator.Result.FREEZE_END) {
16709                    cache.state = ScrollabilityCache.OFF;
16710                } else {
16711                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
16712                }
16713
16714                // This will make the scroll bars inval themselves after
16715                // drawing. We only want this when we're fading so that
16716                // we prevent excessive redraws
16717                invalidate = true;
16718            } else {
16719                // We're just on -- but we may have been fading before so
16720                // reset alpha
16721                cache.scrollBar.mutate().setAlpha(255);
16722            }
16723
16724            final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled();
16725            final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled()
16726                    && !isVerticalScrollBarHidden();
16727
16728            // Fork out the scroll bar drawing for round wearable devices.
16729            if (mRoundScrollbarRenderer != null) {
16730                if (drawVerticalScrollBar) {
16731                    final Rect bounds = cache.mScrollBarBounds;
16732                    getVerticalScrollBarBounds(bounds, null);
16733                    mRoundScrollbarRenderer.drawRoundScrollbars(
16734                            canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds);
16735                    if (invalidate) {
16736                        invalidate();
16737                    }
16738                }
16739                // Do not draw horizontal scroll bars for round wearable devices.
16740            } else if (drawVerticalScrollBar || drawHorizontalScrollBar) {
16741                final ScrollBarDrawable scrollBar = cache.scrollBar;
16742
16743                if (drawHorizontalScrollBar) {
16744                    scrollBar.setParameters(computeHorizontalScrollRange(),
16745                            computeHorizontalScrollOffset(),
16746                            computeHorizontalScrollExtent(), false);
16747                    final Rect bounds = cache.mScrollBarBounds;
16748                    getHorizontalScrollBarBounds(bounds, null);
16749                    onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16750                            bounds.right, bounds.bottom);
16751                    if (invalidate) {
16752                        invalidate(bounds);
16753                    }
16754                }
16755
16756                if (drawVerticalScrollBar) {
16757                    scrollBar.setParameters(computeVerticalScrollRange(),
16758                            computeVerticalScrollOffset(),
16759                            computeVerticalScrollExtent(), true);
16760                    final Rect bounds = cache.mScrollBarBounds;
16761                    getVerticalScrollBarBounds(bounds, null);
16762                    onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top,
16763                            bounds.right, bounds.bottom);
16764                    if (invalidate) {
16765                        invalidate(bounds);
16766                    }
16767                }
16768            }
16769        }
16770    }
16771
16772    /**
16773     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
16774     * FastScroller is visible.
16775     * @return whether to temporarily hide the vertical scrollbar
16776     * @hide
16777     */
16778    protected boolean isVerticalScrollBarHidden() {
16779        return false;
16780    }
16781
16782    /**
16783     * <p>Draw the horizontal scrollbar if
16784     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
16785     *
16786     * @param canvas the canvas on which to draw the scrollbar
16787     * @param scrollBar the scrollbar's drawable
16788     *
16789     * @see #isHorizontalScrollBarEnabled()
16790     * @see #computeHorizontalScrollRange()
16791     * @see #computeHorizontalScrollExtent()
16792     * @see #computeHorizontalScrollOffset()
16793     * @see android.widget.ScrollBarDrawable
16794     * @hide
16795     */
16796    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
16797            int l, int t, int r, int b) {
16798        scrollBar.setBounds(l, t, r, b);
16799        scrollBar.draw(canvas);
16800    }
16801
16802    /**
16803     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
16804     * returns true.</p>
16805     *
16806     * @param canvas the canvas on which to draw the scrollbar
16807     * @param scrollBar the scrollbar's drawable
16808     *
16809     * @see #isVerticalScrollBarEnabled()
16810     * @see #computeVerticalScrollRange()
16811     * @see #computeVerticalScrollExtent()
16812     * @see #computeVerticalScrollOffset()
16813     * @see android.widget.ScrollBarDrawable
16814     * @hide
16815     */
16816    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
16817            int l, int t, int r, int b) {
16818        scrollBar.setBounds(l, t, r, b);
16819        scrollBar.draw(canvas);
16820    }
16821
16822    /**
16823     * Implement this to do your drawing.
16824     *
16825     * @param canvas the canvas on which the background will be drawn
16826     */
16827    protected void onDraw(Canvas canvas) {
16828    }
16829
16830    /*
16831     * Caller is responsible for calling requestLayout if necessary.
16832     * (This allows addViewInLayout to not request a new layout.)
16833     */
16834    void assignParent(ViewParent parent) {
16835        if (mParent == null) {
16836            mParent = parent;
16837        } else if (parent == null) {
16838            mParent = null;
16839        } else {
16840            throw new RuntimeException("view " + this + " being added, but"
16841                    + " it already has a parent");
16842        }
16843    }
16844
16845    /**
16846     * This is called when the view is attached to a window.  At this point it
16847     * has a Surface and will start drawing.  Note that this function is
16848     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
16849     * however it may be called any time before the first onDraw -- including
16850     * before or after {@link #onMeasure(int, int)}.
16851     *
16852     * @see #onDetachedFromWindow()
16853     */
16854    @CallSuper
16855    protected void onAttachedToWindow() {
16856        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
16857            mParent.requestTransparentRegion(this);
16858        }
16859
16860        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
16861
16862        jumpDrawablesToCurrentState();
16863
16864        resetSubtreeAccessibilityStateChanged();
16865
16866        // rebuild, since Outline not maintained while View is detached
16867        rebuildOutline();
16868
16869        if (isFocused()) {
16870            InputMethodManager imm = InputMethodManager.peekInstance();
16871            if (imm != null) {
16872                imm.focusIn(this);
16873            }
16874        }
16875    }
16876
16877    /**
16878     * Resolve all RTL related properties.
16879     *
16880     * @return true if resolution of RTL properties has been done
16881     *
16882     * @hide
16883     */
16884    public boolean resolveRtlPropertiesIfNeeded() {
16885        if (!needRtlPropertiesResolution()) return false;
16886
16887        // Order is important here: LayoutDirection MUST be resolved first
16888        if (!isLayoutDirectionResolved()) {
16889            resolveLayoutDirection();
16890            resolveLayoutParams();
16891        }
16892        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
16893        if (!isTextDirectionResolved()) {
16894            resolveTextDirection();
16895        }
16896        if (!isTextAlignmentResolved()) {
16897            resolveTextAlignment();
16898        }
16899        // Should resolve Drawables before Padding because we need the layout direction of the
16900        // Drawable to correctly resolve Padding.
16901        if (!areDrawablesResolved()) {
16902            resolveDrawables();
16903        }
16904        if (!isPaddingResolved()) {
16905            resolvePadding();
16906        }
16907        onRtlPropertiesChanged(getLayoutDirection());
16908        return true;
16909    }
16910
16911    /**
16912     * Reset resolution of all RTL related properties.
16913     *
16914     * @hide
16915     */
16916    public void resetRtlProperties() {
16917        resetResolvedLayoutDirection();
16918        resetResolvedTextDirection();
16919        resetResolvedTextAlignment();
16920        resetResolvedPadding();
16921        resetResolvedDrawables();
16922    }
16923
16924    /**
16925     * @see #onScreenStateChanged(int)
16926     */
16927    void dispatchScreenStateChanged(int screenState) {
16928        onScreenStateChanged(screenState);
16929    }
16930
16931    /**
16932     * This method is called whenever the state of the screen this view is
16933     * attached to changes. A state change will usually occurs when the screen
16934     * turns on or off (whether it happens automatically or the user does it
16935     * manually.)
16936     *
16937     * @param screenState The new state of the screen. Can be either
16938     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
16939     */
16940    public void onScreenStateChanged(int screenState) {
16941    }
16942
16943    /**
16944     * @see #onMovedToDisplay(int, Configuration)
16945     */
16946    void dispatchMovedToDisplay(Display display, Configuration config) {
16947        mAttachInfo.mDisplay = display;
16948        mAttachInfo.mDisplayState = display.getState();
16949        onMovedToDisplay(display.getDisplayId(), config);
16950    }
16951
16952    /**
16953     * Called by the system when the hosting activity is moved from one display to another without
16954     * recreation. This means that the activity is declared to handle all changes to configuration
16955     * that happened when it was switched to another display, so it wasn't destroyed and created
16956     * again.
16957     *
16958     * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the
16959     * applied configuration actually changed. It is up to app developer to choose whether to handle
16960     * the change in this method or in the following {@link #onConfigurationChanged(Configuration)}
16961     * call.
16962     *
16963     * <p>Use this callback to track changes to the displays if some functionality relies on an
16964     * association with some display properties.
16965     *
16966     * @param displayId The id of the display to which the view was moved.
16967     * @param config Configuration of the resources on new display after move.
16968     *
16969     * @see #onConfigurationChanged(Configuration)
16970     * @hide
16971     */
16972    public void onMovedToDisplay(int displayId, Configuration config) {
16973    }
16974
16975    /**
16976     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
16977     */
16978    private boolean hasRtlSupport() {
16979        return mContext.getApplicationInfo().hasRtlSupport();
16980    }
16981
16982    /**
16983     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
16984     * RTL not supported)
16985     */
16986    private boolean isRtlCompatibilityMode() {
16987        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
16988        return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport();
16989    }
16990
16991    /**
16992     * @return true if RTL properties need resolution.
16993     *
16994     */
16995    private boolean needRtlPropertiesResolution() {
16996        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
16997    }
16998
16999    /**
17000     * Called when any RTL property (layout direction or text direction or text alignment) has
17001     * been changed.
17002     *
17003     * Subclasses need to override this method to take care of cached information that depends on the
17004     * resolved layout direction, or to inform child views that inherit their layout direction.
17005     *
17006     * The default implementation does nothing.
17007     *
17008     * @param layoutDirection the direction of the layout
17009     *
17010     * @see #LAYOUT_DIRECTION_LTR
17011     * @see #LAYOUT_DIRECTION_RTL
17012     */
17013    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
17014    }
17015
17016    /**
17017     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
17018     * that the parent directionality can and will be resolved before its children.
17019     *
17020     * @return true if resolution has been done, false otherwise.
17021     *
17022     * @hide
17023     */
17024    public boolean resolveLayoutDirection() {
17025        // Clear any previous layout direction resolution
17026        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
17027
17028        if (hasRtlSupport()) {
17029            // Set resolved depending on layout direction
17030            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
17031                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
17032                case LAYOUT_DIRECTION_INHERIT:
17033                    // We cannot resolve yet. LTR is by default and let the resolution happen again
17034                    // later to get the correct resolved value
17035                    if (!canResolveLayoutDirection()) return false;
17036
17037                    // Parent has not yet resolved, LTR is still the default
17038                    try {
17039                        if (!mParent.isLayoutDirectionResolved()) return false;
17040
17041                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
17042                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17043                        }
17044                    } catch (AbstractMethodError e) {
17045                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
17046                                " does not fully implement ViewParent", e);
17047                    }
17048                    break;
17049                case LAYOUT_DIRECTION_RTL:
17050                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17051                    break;
17052                case LAYOUT_DIRECTION_LOCALE:
17053                    if((LAYOUT_DIRECTION_RTL ==
17054                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
17055                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
17056                    }
17057                    break;
17058                default:
17059                    // Nothing to do, LTR by default
17060            }
17061        }
17062
17063        // Set to resolved
17064        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
17065        return true;
17066    }
17067
17068    /**
17069     * Check if layout direction resolution can be done.
17070     *
17071     * @return true if layout direction resolution can be done otherwise return false.
17072     */
17073    public boolean canResolveLayoutDirection() {
17074        switch (getRawLayoutDirection()) {
17075            case LAYOUT_DIRECTION_INHERIT:
17076                if (mParent != null) {
17077                    try {
17078                        return mParent.canResolveLayoutDirection();
17079                    } catch (AbstractMethodError e) {
17080                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
17081                                " does not fully implement ViewParent", e);
17082                    }
17083                }
17084                return false;
17085
17086            default:
17087                return true;
17088        }
17089    }
17090
17091    /**
17092     * Reset the resolved layout direction. Layout direction will be resolved during a call to
17093     * {@link #onMeasure(int, int)}.
17094     *
17095     * @hide
17096     */
17097    public void resetResolvedLayoutDirection() {
17098        // Reset the current resolved bits
17099        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
17100    }
17101
17102    /**
17103     * @return true if the layout direction is inherited.
17104     *
17105     * @hide
17106     */
17107    public boolean isLayoutDirectionInherited() {
17108        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
17109    }
17110
17111    /**
17112     * @return true if layout direction has been resolved.
17113     */
17114    public boolean isLayoutDirectionResolved() {
17115        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
17116    }
17117
17118    /**
17119     * Return if padding has been resolved
17120     *
17121     * @hide
17122     */
17123    boolean isPaddingResolved() {
17124        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
17125    }
17126
17127    /**
17128     * Resolves padding depending on layout direction, if applicable, and
17129     * recomputes internal padding values to adjust for scroll bars.
17130     *
17131     * @hide
17132     */
17133    public void resolvePadding() {
17134        final int resolvedLayoutDirection = getLayoutDirection();
17135
17136        if (!isRtlCompatibilityMode()) {
17137            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
17138            // If start / end padding are defined, they will be resolved (hence overriding) to
17139            // left / right or right / left depending on the resolved layout direction.
17140            // If start / end padding are not defined, use the left / right ones.
17141            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
17142                Rect padding = sThreadLocal.get();
17143                if (padding == null) {
17144                    padding = new Rect();
17145                    sThreadLocal.set(padding);
17146                }
17147                mBackground.getPadding(padding);
17148                if (!mLeftPaddingDefined) {
17149                    mUserPaddingLeftInitial = padding.left;
17150                }
17151                if (!mRightPaddingDefined) {
17152                    mUserPaddingRightInitial = padding.right;
17153                }
17154            }
17155            switch (resolvedLayoutDirection) {
17156                case LAYOUT_DIRECTION_RTL:
17157                    if (mUserPaddingStart != UNDEFINED_PADDING) {
17158                        mUserPaddingRight = mUserPaddingStart;
17159                    } else {
17160                        mUserPaddingRight = mUserPaddingRightInitial;
17161                    }
17162                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
17163                        mUserPaddingLeft = mUserPaddingEnd;
17164                    } else {
17165                        mUserPaddingLeft = mUserPaddingLeftInitial;
17166                    }
17167                    break;
17168                case LAYOUT_DIRECTION_LTR:
17169                default:
17170                    if (mUserPaddingStart != UNDEFINED_PADDING) {
17171                        mUserPaddingLeft = mUserPaddingStart;
17172                    } else {
17173                        mUserPaddingLeft = mUserPaddingLeftInitial;
17174                    }
17175                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
17176                        mUserPaddingRight = mUserPaddingEnd;
17177                    } else {
17178                        mUserPaddingRight = mUserPaddingRightInitial;
17179                    }
17180            }
17181
17182            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
17183        }
17184
17185        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
17186        onRtlPropertiesChanged(resolvedLayoutDirection);
17187
17188        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
17189    }
17190
17191    /**
17192     * Reset the resolved layout direction.
17193     *
17194     * @hide
17195     */
17196    public void resetResolvedPadding() {
17197        resetResolvedPaddingInternal();
17198    }
17199
17200    /**
17201     * Used when we only want to reset *this* view's padding and not trigger overrides
17202     * in ViewGroup that reset children too.
17203     */
17204    void resetResolvedPaddingInternal() {
17205        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
17206    }
17207
17208    /**
17209     * This is called when the view is detached from a window.  At this point it
17210     * no longer has a surface for drawing.
17211     *
17212     * @see #onAttachedToWindow()
17213     */
17214    @CallSuper
17215    protected void onDetachedFromWindow() {
17216    }
17217
17218    /**
17219     * This is a framework-internal mirror of onDetachedFromWindow() that's called
17220     * after onDetachedFromWindow().
17221     *
17222     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
17223     * The super method should be called at the end of the overridden method to ensure
17224     * subclasses are destroyed first
17225     *
17226     * @hide
17227     */
17228    @CallSuper
17229    protected void onDetachedFromWindowInternal() {
17230        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
17231        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
17232        mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH;
17233
17234        removeUnsetPressCallback();
17235        removeLongPressCallback();
17236        removePerformClickCallback();
17237        removeSendViewScrolledAccessibilityEventCallback();
17238        stopNestedScroll();
17239
17240        // Anything that started animating right before detach should already
17241        // be in its final state when re-attached.
17242        jumpDrawablesToCurrentState();
17243
17244        destroyDrawingCache();
17245
17246        cleanupDraw();
17247        mCurrentAnimation = null;
17248
17249        if ((mViewFlags & TOOLTIP) == TOOLTIP) {
17250            hideTooltip();
17251        }
17252    }
17253
17254    private void cleanupDraw() {
17255        resetDisplayList();
17256        if (mAttachInfo != null) {
17257            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
17258        }
17259    }
17260
17261    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
17262    }
17263
17264    /**
17265     * @return The number of times this view has been attached to a window
17266     */
17267    protected int getWindowAttachCount() {
17268        return mWindowAttachCount;
17269    }
17270
17271    /**
17272     * Retrieve a unique token identifying the window this view is attached to.
17273     * @return Return the window's token for use in
17274     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
17275     */
17276    public IBinder getWindowToken() {
17277        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
17278    }
17279
17280    /**
17281     * Retrieve the {@link WindowId} for the window this view is
17282     * currently attached to.
17283     */
17284    public WindowId getWindowId() {
17285        if (mAttachInfo == null) {
17286            return null;
17287        }
17288        if (mAttachInfo.mWindowId == null) {
17289            try {
17290                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
17291                        mAttachInfo.mWindowToken);
17292                mAttachInfo.mWindowId = new WindowId(
17293                        mAttachInfo.mIWindowId);
17294            } catch (RemoteException e) {
17295            }
17296        }
17297        return mAttachInfo.mWindowId;
17298    }
17299
17300    /**
17301     * Retrieve a unique token identifying the top-level "real" window of
17302     * the window that this view is attached to.  That is, this is like
17303     * {@link #getWindowToken}, except if the window this view in is a panel
17304     * window (attached to another containing window), then the token of
17305     * the containing window is returned instead.
17306     *
17307     * @return Returns the associated window token, either
17308     * {@link #getWindowToken()} or the containing window's token.
17309     */
17310    public IBinder getApplicationWindowToken() {
17311        AttachInfo ai = mAttachInfo;
17312        if (ai != null) {
17313            IBinder appWindowToken = ai.mPanelParentWindowToken;
17314            if (appWindowToken == null) {
17315                appWindowToken = ai.mWindowToken;
17316            }
17317            return appWindowToken;
17318        }
17319        return null;
17320    }
17321
17322    /**
17323     * Gets the logical display to which the view's window has been attached.
17324     *
17325     * @return The logical display, or null if the view is not currently attached to a window.
17326     */
17327    public Display getDisplay() {
17328        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
17329    }
17330
17331    /**
17332     * Retrieve private session object this view hierarchy is using to
17333     * communicate with the window manager.
17334     * @return the session object to communicate with the window manager
17335     */
17336    /*package*/ IWindowSession getWindowSession() {
17337        return mAttachInfo != null ? mAttachInfo.mSession : null;
17338    }
17339
17340    /**
17341     * Return the visibility value of the least visible component passed.
17342     */
17343    int combineVisibility(int vis1, int vis2) {
17344        // This works because VISIBLE < INVISIBLE < GONE.
17345        return Math.max(vis1, vis2);
17346    }
17347
17348    /**
17349     * @param info the {@link android.view.View.AttachInfo} to associated with
17350     *        this view
17351     */
17352    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
17353        mAttachInfo = info;
17354        if (mOverlay != null) {
17355            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
17356        }
17357        mWindowAttachCount++;
17358        // We will need to evaluate the drawable state at least once.
17359        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17360        if (mFloatingTreeObserver != null) {
17361            info.mTreeObserver.merge(mFloatingTreeObserver);
17362            mFloatingTreeObserver = null;
17363        }
17364
17365        registerPendingFrameMetricsObservers();
17366
17367        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
17368            mAttachInfo.mScrollContainers.add(this);
17369            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
17370        }
17371        // Transfer all pending runnables.
17372        if (mRunQueue != null) {
17373            mRunQueue.executeActions(info.mHandler);
17374            mRunQueue = null;
17375        }
17376        performCollectViewAttributes(mAttachInfo, visibility);
17377        onAttachedToWindow();
17378
17379        ListenerInfo li = mListenerInfo;
17380        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17381                li != null ? li.mOnAttachStateChangeListeners : null;
17382        if (listeners != null && listeners.size() > 0) {
17383            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17384            // perform the dispatching. The iterator is a safe guard against listeners that
17385            // could mutate the list by calling the various add/remove methods. This prevents
17386            // the array from being modified while we iterate it.
17387            for (OnAttachStateChangeListener listener : listeners) {
17388                listener.onViewAttachedToWindow(this);
17389            }
17390        }
17391
17392        int vis = info.mWindowVisibility;
17393        if (vis != GONE) {
17394            onWindowVisibilityChanged(vis);
17395            if (isShown()) {
17396                // Calling onVisibilityAggregated directly here since the subtree will also
17397                // receive dispatchAttachedToWindow and this same call
17398                onVisibilityAggregated(vis == VISIBLE);
17399            }
17400        }
17401
17402        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
17403        // As all views in the subtree will already receive dispatchAttachedToWindow
17404        // traversing the subtree again here is not desired.
17405        onVisibilityChanged(this, visibility);
17406
17407        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
17408            // If nobody has evaluated the drawable state yet, then do it now.
17409            refreshDrawableState();
17410        }
17411        needGlobalAttributesUpdate(false);
17412
17413        notifyEnterOrExitForAutoFillIfNeeded(true);
17414    }
17415
17416    void dispatchDetachedFromWindow() {
17417        AttachInfo info = mAttachInfo;
17418        if (info != null) {
17419            int vis = info.mWindowVisibility;
17420            if (vis != GONE) {
17421                onWindowVisibilityChanged(GONE);
17422                if (isShown()) {
17423                    // Invoking onVisibilityAggregated directly here since the subtree
17424                    // will also receive detached from window
17425                    onVisibilityAggregated(false);
17426                }
17427            }
17428        }
17429
17430        onDetachedFromWindow();
17431        onDetachedFromWindowInternal();
17432
17433        InputMethodManager imm = InputMethodManager.peekInstance();
17434        if (imm != null) {
17435            imm.onViewDetachedFromWindow(this);
17436        }
17437
17438        ListenerInfo li = mListenerInfo;
17439        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
17440                li != null ? li.mOnAttachStateChangeListeners : null;
17441        if (listeners != null && listeners.size() > 0) {
17442            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
17443            // perform the dispatching. The iterator is a safe guard against listeners that
17444            // could mutate the list by calling the various add/remove methods. This prevents
17445            // the array from being modified while we iterate it.
17446            for (OnAttachStateChangeListener listener : listeners) {
17447                listener.onViewDetachedFromWindow(this);
17448            }
17449        }
17450
17451        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
17452            mAttachInfo.mScrollContainers.remove(this);
17453            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
17454        }
17455
17456        mAttachInfo = null;
17457        if (mOverlay != null) {
17458            mOverlay.getOverlayView().dispatchDetachedFromWindow();
17459        }
17460
17461        notifyEnterOrExitForAutoFillIfNeeded(false);
17462    }
17463
17464    /**
17465     * Cancel any deferred high-level input events that were previously posted to the event queue.
17466     *
17467     * <p>Many views post high-level events such as click handlers to the event queue
17468     * to run deferred in order to preserve a desired user experience - clearing visible
17469     * pressed states before executing, etc. This method will abort any events of this nature
17470     * that are currently in flight.</p>
17471     *
17472     * <p>Custom views that generate their own high-level deferred input events should override
17473     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
17474     *
17475     * <p>This will also cancel pending input events for any child views.</p>
17476     *
17477     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
17478     * This will not impact newer events posted after this call that may occur as a result of
17479     * lower-level input events still waiting in the queue. If you are trying to prevent
17480     * double-submitted  events for the duration of some sort of asynchronous transaction
17481     * you should also take other steps to protect against unexpected double inputs e.g. calling
17482     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
17483     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
17484     */
17485    public final void cancelPendingInputEvents() {
17486        dispatchCancelPendingInputEvents();
17487    }
17488
17489    /**
17490     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
17491     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
17492     */
17493    void dispatchCancelPendingInputEvents() {
17494        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
17495        onCancelPendingInputEvents();
17496        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
17497            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
17498                    " did not call through to super.onCancelPendingInputEvents()");
17499        }
17500    }
17501
17502    /**
17503     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
17504     * a parent view.
17505     *
17506     * <p>This method is responsible for removing any pending high-level input events that were
17507     * posted to the event queue to run later. Custom view classes that post their own deferred
17508     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
17509     * {@link android.os.Handler} should override this method, call
17510     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
17511     * </p>
17512     */
17513    public void onCancelPendingInputEvents() {
17514        removePerformClickCallback();
17515        cancelLongPress();
17516        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
17517    }
17518
17519    /**
17520     * Store this view hierarchy's frozen state into the given container.
17521     *
17522     * @param container The SparseArray in which to save the view's state.
17523     *
17524     * @see #restoreHierarchyState(android.util.SparseArray)
17525     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17526     * @see #onSaveInstanceState()
17527     */
17528    public void saveHierarchyState(SparseArray<Parcelable> container) {
17529        dispatchSaveInstanceState(container);
17530    }
17531
17532    /**
17533     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
17534     * this view and its children. May be overridden to modify how freezing happens to a
17535     * view's children; for example, some views may want to not store state for their children.
17536     *
17537     * @param container The SparseArray in which to save the view's state.
17538     *
17539     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17540     * @see #saveHierarchyState(android.util.SparseArray)
17541     * @see #onSaveInstanceState()
17542     */
17543    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
17544        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
17545            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17546            Parcelable state = onSaveInstanceState();
17547            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17548                throw new IllegalStateException(
17549                        "Derived class did not call super.onSaveInstanceState()");
17550            }
17551            if (state != null) {
17552                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
17553                // + ": " + state);
17554                container.put(mID, state);
17555            }
17556        }
17557    }
17558
17559    /**
17560     * Hook allowing a view to generate a representation of its internal state
17561     * that can later be used to create a new instance with that same state.
17562     * This state should only contain information that is not persistent or can
17563     * not be reconstructed later. For example, you will never store your
17564     * current position on screen because that will be computed again when a
17565     * new instance of the view is placed in its view hierarchy.
17566     * <p>
17567     * Some examples of things you may store here: the current cursor position
17568     * in a text view (but usually not the text itself since that is stored in a
17569     * content provider or other persistent storage), the currently selected
17570     * item in a list view.
17571     *
17572     * @return Returns a Parcelable object containing the view's current dynamic
17573     *         state, or null if there is nothing interesting to save.
17574     * @see #onRestoreInstanceState(Parcelable)
17575     * @see #saveHierarchyState(SparseArray)
17576     * @see #dispatchSaveInstanceState(SparseArray)
17577     * @see #setSaveEnabled(boolean)
17578     */
17579    @CallSuper
17580    @Nullable protected Parcelable onSaveInstanceState() {
17581        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17582        if (mStartActivityRequestWho != null || isAutofilled()
17583                || mAutofillViewId > LAST_APP_AUTOFILL_ID) {
17584            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
17585
17586            if (mStartActivityRequestWho != null) {
17587                state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED;
17588            }
17589
17590            if (isAutofilled()) {
17591                state.mSavedData |= BaseSavedState.IS_AUTOFILLED;
17592            }
17593
17594            if (mAutofillViewId > LAST_APP_AUTOFILL_ID) {
17595                state.mSavedData |= BaseSavedState.AUTOFILL_ID;
17596            }
17597
17598            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
17599            state.mIsAutofilled = isAutofilled();
17600            state.mAutofillViewId = mAutofillViewId;
17601            return state;
17602        }
17603        return BaseSavedState.EMPTY_STATE;
17604    }
17605
17606    /**
17607     * Restore this view hierarchy's frozen state from the given container.
17608     *
17609     * @param container The SparseArray which holds previously frozen states.
17610     *
17611     * @see #saveHierarchyState(android.util.SparseArray)
17612     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17613     * @see #onRestoreInstanceState(android.os.Parcelable)
17614     */
17615    public void restoreHierarchyState(SparseArray<Parcelable> container) {
17616        dispatchRestoreInstanceState(container);
17617    }
17618
17619    /**
17620     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
17621     * state for this view and its children. May be overridden to modify how restoring
17622     * happens to a view's children; for example, some views may want to not store state
17623     * for their children.
17624     *
17625     * @param container The SparseArray which holds previously saved state.
17626     *
17627     * @see #dispatchSaveInstanceState(android.util.SparseArray)
17628     * @see #restoreHierarchyState(android.util.SparseArray)
17629     * @see #onRestoreInstanceState(android.os.Parcelable)
17630     */
17631    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
17632        if (mID != NO_ID) {
17633            Parcelable state = container.get(mID);
17634            if (state != null) {
17635                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
17636                // + ": " + state);
17637                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
17638                onRestoreInstanceState(state);
17639                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
17640                    throw new IllegalStateException(
17641                            "Derived class did not call super.onRestoreInstanceState()");
17642                }
17643            }
17644        }
17645    }
17646
17647    /**
17648     * Hook allowing a view to re-apply a representation of its internal state that had previously
17649     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
17650     * null state.
17651     *
17652     * @param state The frozen state that had previously been returned by
17653     *        {@link #onSaveInstanceState}.
17654     *
17655     * @see #onSaveInstanceState()
17656     * @see #restoreHierarchyState(android.util.SparseArray)
17657     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
17658     */
17659    @CallSuper
17660    protected void onRestoreInstanceState(Parcelable state) {
17661        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
17662        if (state != null && !(state instanceof AbsSavedState)) {
17663            throw new IllegalArgumentException("Wrong state class, expecting View State but "
17664                    + "received " + state.getClass().toString() + " instead. This usually happens "
17665                    + "when two views of different type have the same id in the same hierarchy. "
17666                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
17667                    + "other views do not use the same id.");
17668        }
17669        if (state != null && state instanceof BaseSavedState) {
17670            BaseSavedState baseState = (BaseSavedState) state;
17671
17672            if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) {
17673                mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved;
17674            }
17675            if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) {
17676                setAutofilled(baseState.mIsAutofilled);
17677            }
17678            if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) {
17679                mAutofillViewId = baseState.mAutofillViewId;
17680            }
17681        }
17682    }
17683
17684    /**
17685     * <p>Return the time at which the drawing of the view hierarchy started.</p>
17686     *
17687     * @return the drawing start time in milliseconds
17688     */
17689    public long getDrawingTime() {
17690        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
17691    }
17692
17693    /**
17694     * <p>Enables or disables the duplication of the parent's state into this view. When
17695     * duplication is enabled, this view gets its drawable state from its parent rather
17696     * than from its own internal properties.</p>
17697     *
17698     * <p>Note: in the current implementation, setting this property to true after the
17699     * view was added to a ViewGroup might have no effect at all. This property should
17700     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
17701     *
17702     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
17703     * property is enabled, an exception will be thrown.</p>
17704     *
17705     * <p>Note: if the child view uses and updates additional states which are unknown to the
17706     * parent, these states should not be affected by this method.</p>
17707     *
17708     * @param enabled True to enable duplication of the parent's drawable state, false
17709     *                to disable it.
17710     *
17711     * @see #getDrawableState()
17712     * @see #isDuplicateParentStateEnabled()
17713     */
17714    public void setDuplicateParentStateEnabled(boolean enabled) {
17715        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
17716    }
17717
17718    /**
17719     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
17720     *
17721     * @return True if this view's drawable state is duplicated from the parent,
17722     *         false otherwise
17723     *
17724     * @see #getDrawableState()
17725     * @see #setDuplicateParentStateEnabled(boolean)
17726     */
17727    public boolean isDuplicateParentStateEnabled() {
17728        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
17729    }
17730
17731    /**
17732     * <p>Specifies the type of layer backing this view. The layer can be
17733     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17734     * {@link #LAYER_TYPE_HARDWARE}.</p>
17735     *
17736     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17737     * instance that controls how the layer is composed on screen. The following
17738     * properties of the paint are taken into account when composing the layer:</p>
17739     * <ul>
17740     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17741     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17742     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17743     * </ul>
17744     *
17745     * <p>If this view has an alpha value set to < 1.0 by calling
17746     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
17747     * by this view's alpha value.</p>
17748     *
17749     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
17750     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
17751     * for more information on when and how to use layers.</p>
17752     *
17753     * @param layerType The type of layer to use with this view, must be one of
17754     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17755     *        {@link #LAYER_TYPE_HARDWARE}
17756     * @param paint The paint used to compose the layer. This argument is optional
17757     *        and can be null. It is ignored when the layer type is
17758     *        {@link #LAYER_TYPE_NONE}
17759     *
17760     * @see #getLayerType()
17761     * @see #LAYER_TYPE_NONE
17762     * @see #LAYER_TYPE_SOFTWARE
17763     * @see #LAYER_TYPE_HARDWARE
17764     * @see #setAlpha(float)
17765     *
17766     * @attr ref android.R.styleable#View_layerType
17767     */
17768    public void setLayerType(int layerType, @Nullable Paint paint) {
17769        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
17770            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
17771                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
17772        }
17773
17774        boolean typeChanged = mRenderNode.setLayerType(layerType);
17775
17776        if (!typeChanged) {
17777            setLayerPaint(paint);
17778            return;
17779        }
17780
17781        if (layerType != LAYER_TYPE_SOFTWARE) {
17782            // Destroy any previous software drawing cache if present
17783            // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up
17784            // drawing cache created in View#draw when drawing to a SW canvas.
17785            destroyDrawingCache();
17786        }
17787
17788        mLayerType = layerType;
17789        mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
17790        mRenderNode.setLayerPaint(mLayerPaint);
17791
17792        // draw() behaves differently if we are on a layer, so we need to
17793        // invalidate() here
17794        invalidateParentCaches();
17795        invalidate(true);
17796    }
17797
17798    /**
17799     * Updates the {@link Paint} object used with the current layer (used only if the current
17800     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
17801     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
17802     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
17803     * ensure that the view gets redrawn immediately.
17804     *
17805     * <p>A layer is associated with an optional {@link android.graphics.Paint}
17806     * instance that controls how the layer is composed on screen. The following
17807     * properties of the paint are taken into account when composing the layer:</p>
17808     * <ul>
17809     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
17810     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
17811     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
17812     * </ul>
17813     *
17814     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
17815     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
17816     *
17817     * @param paint The paint used to compose the layer. This argument is optional
17818     *        and can be null. It is ignored when the layer type is
17819     *        {@link #LAYER_TYPE_NONE}
17820     *
17821     * @see #setLayerType(int, android.graphics.Paint)
17822     */
17823    public void setLayerPaint(@Nullable Paint paint) {
17824        int layerType = getLayerType();
17825        if (layerType != LAYER_TYPE_NONE) {
17826            mLayerPaint = paint;
17827            if (layerType == LAYER_TYPE_HARDWARE) {
17828                if (mRenderNode.setLayerPaint(paint)) {
17829                    invalidateViewProperty(false, false);
17830                }
17831            } else {
17832                invalidate();
17833            }
17834        }
17835    }
17836
17837    /**
17838     * Indicates what type of layer is currently associated with this view. By default
17839     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
17840     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
17841     * for more information on the different types of layers.
17842     *
17843     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
17844     *         {@link #LAYER_TYPE_HARDWARE}
17845     *
17846     * @see #setLayerType(int, android.graphics.Paint)
17847     * @see #buildLayer()
17848     * @see #LAYER_TYPE_NONE
17849     * @see #LAYER_TYPE_SOFTWARE
17850     * @see #LAYER_TYPE_HARDWARE
17851     */
17852    public int getLayerType() {
17853        return mLayerType;
17854    }
17855
17856    /**
17857     * Forces this view's layer to be created and this view to be rendered
17858     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
17859     * invoking this method will have no effect.
17860     *
17861     * This method can for instance be used to render a view into its layer before
17862     * starting an animation. If this view is complex, rendering into the layer
17863     * before starting the animation will avoid skipping frames.
17864     *
17865     * @throws IllegalStateException If this view is not attached to a window
17866     *
17867     * @see #setLayerType(int, android.graphics.Paint)
17868     */
17869    public void buildLayer() {
17870        if (mLayerType == LAYER_TYPE_NONE) return;
17871
17872        final AttachInfo attachInfo = mAttachInfo;
17873        if (attachInfo == null) {
17874            throw new IllegalStateException("This view must be attached to a window first");
17875        }
17876
17877        if (getWidth() == 0 || getHeight() == 0) {
17878            return;
17879        }
17880
17881        switch (mLayerType) {
17882            case LAYER_TYPE_HARDWARE:
17883                updateDisplayListIfDirty();
17884                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
17885                    attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
17886                }
17887                break;
17888            case LAYER_TYPE_SOFTWARE:
17889                buildDrawingCache(true);
17890                break;
17891        }
17892    }
17893
17894    /**
17895     * Destroys all hardware rendering resources. This method is invoked
17896     * when the system needs to reclaim resources. Upon execution of this
17897     * method, you should free any OpenGL resources created by the view.
17898     *
17899     * Note: you <strong>must</strong> call
17900     * <code>super.destroyHardwareResources()</code> when overriding
17901     * this method.
17902     *
17903     * @hide
17904     */
17905    @CallSuper
17906    protected void destroyHardwareResources() {
17907        if (mOverlay != null) {
17908            mOverlay.getOverlayView().destroyHardwareResources();
17909        }
17910        if (mGhostView != null) {
17911            mGhostView.destroyHardwareResources();
17912        }
17913    }
17914
17915    /**
17916     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
17917     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
17918     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
17919     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
17920     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
17921     * null.</p>
17922     *
17923     * <p>Enabling the drawing cache is similar to
17924     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
17925     * acceleration is turned off. When hardware acceleration is turned on, enabling the
17926     * drawing cache has no effect on rendering because the system uses a different mechanism
17927     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
17928     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
17929     * for information on how to enable software and hardware layers.</p>
17930     *
17931     * <p>This API can be used to manually generate
17932     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
17933     * {@link #getDrawingCache()}.</p>
17934     *
17935     * @param enabled true to enable the drawing cache, false otherwise
17936     *
17937     * @see #isDrawingCacheEnabled()
17938     * @see #getDrawingCache()
17939     * @see #buildDrawingCache()
17940     * @see #setLayerType(int, android.graphics.Paint)
17941     */
17942    public void setDrawingCacheEnabled(boolean enabled) {
17943        mCachingFailed = false;
17944        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
17945    }
17946
17947    /**
17948     * <p>Indicates whether the drawing cache is enabled for this view.</p>
17949     *
17950     * @return true if the drawing cache is enabled
17951     *
17952     * @see #setDrawingCacheEnabled(boolean)
17953     * @see #getDrawingCache()
17954     */
17955    @ViewDebug.ExportedProperty(category = "drawing")
17956    public boolean isDrawingCacheEnabled() {
17957        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
17958    }
17959
17960    /**
17961     * Debugging utility which recursively outputs the dirty state of a view and its
17962     * descendants.
17963     *
17964     * @hide
17965     */
17966    @SuppressWarnings({"UnusedDeclaration"})
17967    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
17968        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
17969                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
17970                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
17971                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
17972        if (clear) {
17973            mPrivateFlags &= clearMask;
17974        }
17975        if (this instanceof ViewGroup) {
17976            ViewGroup parent = (ViewGroup) this;
17977            final int count = parent.getChildCount();
17978            for (int i = 0; i < count; i++) {
17979                final View child = parent.getChildAt(i);
17980                child.outputDirtyFlags(indent + "  ", clear, clearMask);
17981            }
17982        }
17983    }
17984
17985    /**
17986     * This method is used by ViewGroup to cause its children to restore or recreate their
17987     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
17988     * to recreate its own display list, which would happen if it went through the normal
17989     * draw/dispatchDraw mechanisms.
17990     *
17991     * @hide
17992     */
17993    protected void dispatchGetDisplayList() {}
17994
17995    /**
17996     * A view that is not attached or hardware accelerated cannot create a display list.
17997     * This method checks these conditions and returns the appropriate result.
17998     *
17999     * @return true if view has the ability to create a display list, false otherwise.
18000     *
18001     * @hide
18002     */
18003    public boolean canHaveDisplayList() {
18004        return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null);
18005    }
18006
18007    /**
18008     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
18009     * @hide
18010     */
18011    @NonNull
18012    public RenderNode updateDisplayListIfDirty() {
18013        final RenderNode renderNode = mRenderNode;
18014        if (!canHaveDisplayList()) {
18015            // can't populate RenderNode, don't try
18016            return renderNode;
18017        }
18018
18019        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
18020                || !renderNode.isValid()
18021                || (mRecreateDisplayList)) {
18022            // Don't need to recreate the display list, just need to tell our
18023            // children to restore/recreate theirs
18024            if (renderNode.isValid()
18025                    && !mRecreateDisplayList) {
18026                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18027                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18028                dispatchGetDisplayList();
18029
18030                return renderNode; // no work needed
18031            }
18032
18033            // If we got here, we're recreating it. Mark it as such to ensure that
18034            // we copy in child display lists into ours in drawChild()
18035            mRecreateDisplayList = true;
18036
18037            int width = mRight - mLeft;
18038            int height = mBottom - mTop;
18039            int layerType = getLayerType();
18040
18041            final DisplayListCanvas canvas = renderNode.start(width, height);
18042            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
18043
18044            try {
18045                if (layerType == LAYER_TYPE_SOFTWARE) {
18046                    buildDrawingCache(true);
18047                    Bitmap cache = getDrawingCache(true);
18048                    if (cache != null) {
18049                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
18050                    }
18051                } else {
18052                    computeScroll();
18053
18054                    canvas.translate(-mScrollX, -mScrollY);
18055                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18056                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18057
18058                    // Fast path for layouts with no backgrounds
18059                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18060                        dispatchDraw(canvas);
18061                        drawAutofilledHighlight(canvas);
18062                        if (mOverlay != null && !mOverlay.isEmpty()) {
18063                            mOverlay.getOverlayView().draw(canvas);
18064                        }
18065                        if (debugDraw()) {
18066                            debugDrawFocus(canvas);
18067                        }
18068                    } else {
18069                        draw(canvas);
18070                    }
18071                }
18072            } finally {
18073                renderNode.end(canvas);
18074                setDisplayListProperties(renderNode);
18075            }
18076        } else {
18077            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
18078            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18079        }
18080        return renderNode;
18081    }
18082
18083    private void resetDisplayList() {
18084        mRenderNode.discardDisplayList();
18085        if (mBackgroundRenderNode != null) {
18086            mBackgroundRenderNode.discardDisplayList();
18087        }
18088    }
18089
18090    /**
18091     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
18092     *
18093     * @return A non-scaled bitmap representing this view or null if cache is disabled.
18094     *
18095     * @see #getDrawingCache(boolean)
18096     */
18097    public Bitmap getDrawingCache() {
18098        return getDrawingCache(false);
18099    }
18100
18101    /**
18102     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
18103     * is null when caching is disabled. If caching is enabled and the cache is not ready,
18104     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
18105     * draw from the cache when the cache is enabled. To benefit from the cache, you must
18106     * request the drawing cache by calling this method and draw it on screen if the
18107     * returned bitmap is not null.</p>
18108     *
18109     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
18110     * this method will create a bitmap of the same size as this view. Because this bitmap
18111     * will be drawn scaled by the parent ViewGroup, the result on screen might show
18112     * scaling artifacts. To avoid such artifacts, you should call this method by setting
18113     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
18114     * size than the view. This implies that your application must be able to handle this
18115     * size.</p>
18116     *
18117     * @param autoScale Indicates whether the generated bitmap should be scaled based on
18118     *        the current density of the screen when the application is in compatibility
18119     *        mode.
18120     *
18121     * @return A bitmap representing this view or null if cache is disabled.
18122     *
18123     * @see #setDrawingCacheEnabled(boolean)
18124     * @see #isDrawingCacheEnabled()
18125     * @see #buildDrawingCache(boolean)
18126     * @see #destroyDrawingCache()
18127     */
18128    public Bitmap getDrawingCache(boolean autoScale) {
18129        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
18130            return null;
18131        }
18132        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
18133            buildDrawingCache(autoScale);
18134        }
18135        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
18136    }
18137
18138    /**
18139     * <p>Frees the resources used by the drawing cache. If you call
18140     * {@link #buildDrawingCache()} manually without calling
18141     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
18142     * should cleanup the cache with this method afterwards.</p>
18143     *
18144     * @see #setDrawingCacheEnabled(boolean)
18145     * @see #buildDrawingCache()
18146     * @see #getDrawingCache()
18147     */
18148    public void destroyDrawingCache() {
18149        if (mDrawingCache != null) {
18150            mDrawingCache.recycle();
18151            mDrawingCache = null;
18152        }
18153        if (mUnscaledDrawingCache != null) {
18154            mUnscaledDrawingCache.recycle();
18155            mUnscaledDrawingCache = null;
18156        }
18157    }
18158
18159    /**
18160     * Setting a solid background color for the drawing cache's bitmaps will improve
18161     * performance and memory usage. Note, though that this should only be used if this
18162     * view will always be drawn on top of a solid color.
18163     *
18164     * @param color The background color to use for the drawing cache's bitmap
18165     *
18166     * @see #setDrawingCacheEnabled(boolean)
18167     * @see #buildDrawingCache()
18168     * @see #getDrawingCache()
18169     */
18170    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
18171        if (color != mDrawingCacheBackgroundColor) {
18172            mDrawingCacheBackgroundColor = color;
18173            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
18174        }
18175    }
18176
18177    /**
18178     * @see #setDrawingCacheBackgroundColor(int)
18179     *
18180     * @return The background color to used for the drawing cache's bitmap
18181     */
18182    @ColorInt
18183    public int getDrawingCacheBackgroundColor() {
18184        return mDrawingCacheBackgroundColor;
18185    }
18186
18187    /**
18188     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
18189     *
18190     * @see #buildDrawingCache(boolean)
18191     */
18192    public void buildDrawingCache() {
18193        buildDrawingCache(false);
18194    }
18195
18196    /**
18197     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
18198     *
18199     * <p>If you call {@link #buildDrawingCache()} manually without calling
18200     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
18201     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
18202     *
18203     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
18204     * this method will create a bitmap of the same size as this view. Because this bitmap
18205     * will be drawn scaled by the parent ViewGroup, the result on screen might show
18206     * scaling artifacts. To avoid such artifacts, you should call this method by setting
18207     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
18208     * size than the view. This implies that your application must be able to handle this
18209     * size.</p>
18210     *
18211     * <p>You should avoid calling this method when hardware acceleration is enabled. If
18212     * you do not need the drawing cache bitmap, calling this method will increase memory
18213     * usage and cause the view to be rendered in software once, thus negatively impacting
18214     * performance.</p>
18215     *
18216     * @see #getDrawingCache()
18217     * @see #destroyDrawingCache()
18218     */
18219    public void buildDrawingCache(boolean autoScale) {
18220        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
18221                mDrawingCache == null : mUnscaledDrawingCache == null)) {
18222            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
18223                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
18224                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
18225            }
18226            try {
18227                buildDrawingCacheImpl(autoScale);
18228            } finally {
18229                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
18230            }
18231        }
18232    }
18233
18234    /**
18235     * private, internal implementation of buildDrawingCache, used to enable tracing
18236     */
18237    private void buildDrawingCacheImpl(boolean autoScale) {
18238        mCachingFailed = false;
18239
18240        int width = mRight - mLeft;
18241        int height = mBottom - mTop;
18242
18243        final AttachInfo attachInfo = mAttachInfo;
18244        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
18245
18246        if (autoScale && scalingRequired) {
18247            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
18248            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
18249        }
18250
18251        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
18252        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
18253        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
18254
18255        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
18256        final long drawingCacheSize =
18257                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
18258        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
18259            if (width > 0 && height > 0) {
18260                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
18261                        + " too large to fit into a software layer (or drawing cache), needs "
18262                        + projectedBitmapSize + " bytes, only "
18263                        + drawingCacheSize + " available");
18264            }
18265            destroyDrawingCache();
18266            mCachingFailed = true;
18267            return;
18268        }
18269
18270        boolean clear = true;
18271        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
18272
18273        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
18274            Bitmap.Config quality;
18275            if (!opaque) {
18276                // Never pick ARGB_4444 because it looks awful
18277                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
18278                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
18279                    case DRAWING_CACHE_QUALITY_AUTO:
18280                    case DRAWING_CACHE_QUALITY_LOW:
18281                    case DRAWING_CACHE_QUALITY_HIGH:
18282                    default:
18283                        quality = Bitmap.Config.ARGB_8888;
18284                        break;
18285                }
18286            } else {
18287                // Optimization for translucent windows
18288                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
18289                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
18290            }
18291
18292            // Try to cleanup memory
18293            if (bitmap != null) bitmap.recycle();
18294
18295            try {
18296                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18297                        width, height, quality);
18298                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
18299                if (autoScale) {
18300                    mDrawingCache = bitmap;
18301                } else {
18302                    mUnscaledDrawingCache = bitmap;
18303                }
18304                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
18305            } catch (OutOfMemoryError e) {
18306                // If there is not enough memory to create the bitmap cache, just
18307                // ignore the issue as bitmap caches are not required to draw the
18308                // view hierarchy
18309                if (autoScale) {
18310                    mDrawingCache = null;
18311                } else {
18312                    mUnscaledDrawingCache = null;
18313                }
18314                mCachingFailed = true;
18315                return;
18316            }
18317
18318            clear = drawingCacheBackgroundColor != 0;
18319        }
18320
18321        Canvas canvas;
18322        if (attachInfo != null) {
18323            canvas = attachInfo.mCanvas;
18324            if (canvas == null) {
18325                canvas = new Canvas();
18326            }
18327            canvas.setBitmap(bitmap);
18328            // Temporarily clobber the cached Canvas in case one of our children
18329            // is also using a drawing cache. Without this, the children would
18330            // steal the canvas by attaching their own bitmap to it and bad, bad
18331            // thing would happen (invisible views, corrupted drawings, etc.)
18332            attachInfo.mCanvas = null;
18333        } else {
18334            // This case should hopefully never or seldom happen
18335            canvas = new Canvas(bitmap);
18336        }
18337
18338        if (clear) {
18339            bitmap.eraseColor(drawingCacheBackgroundColor);
18340        }
18341
18342        computeScroll();
18343        final int restoreCount = canvas.save();
18344
18345        if (autoScale && scalingRequired) {
18346            final float scale = attachInfo.mApplicationScale;
18347            canvas.scale(scale, scale);
18348        }
18349
18350        canvas.translate(-mScrollX, -mScrollY);
18351
18352        mPrivateFlags |= PFLAG_DRAWN;
18353        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
18354                mLayerType != LAYER_TYPE_NONE) {
18355            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
18356        }
18357
18358        // Fast path for layouts with no backgrounds
18359        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18360            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18361            dispatchDraw(canvas);
18362            drawAutofilledHighlight(canvas);
18363            if (mOverlay != null && !mOverlay.isEmpty()) {
18364                mOverlay.getOverlayView().draw(canvas);
18365            }
18366        } else {
18367            draw(canvas);
18368        }
18369
18370        canvas.restoreToCount(restoreCount);
18371        canvas.setBitmap(null);
18372
18373        if (attachInfo != null) {
18374            // Restore the cached Canvas for our siblings
18375            attachInfo.mCanvas = canvas;
18376        }
18377    }
18378
18379    /**
18380     * Create a snapshot of the view into a bitmap.  We should probably make
18381     * some form of this public, but should think about the API.
18382     *
18383     * @hide
18384     */
18385    public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
18386        int width = mRight - mLeft;
18387        int height = mBottom - mTop;
18388
18389        final AttachInfo attachInfo = mAttachInfo;
18390        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
18391        width = (int) ((width * scale) + 0.5f);
18392        height = (int) ((height * scale) + 0.5f);
18393
18394        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
18395                width > 0 ? width : 1, height > 0 ? height : 1, quality);
18396        if (bitmap == null) {
18397            throw new OutOfMemoryError();
18398        }
18399
18400        Resources resources = getResources();
18401        if (resources != null) {
18402            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
18403        }
18404
18405        Canvas canvas;
18406        if (attachInfo != null) {
18407            canvas = attachInfo.mCanvas;
18408            if (canvas == null) {
18409                canvas = new Canvas();
18410            }
18411            canvas.setBitmap(bitmap);
18412            // Temporarily clobber the cached Canvas in case one of our children
18413            // is also using a drawing cache. Without this, the children would
18414            // steal the canvas by attaching their own bitmap to it and bad, bad
18415            // things would happen (invisible views, corrupted drawings, etc.)
18416            attachInfo.mCanvas = null;
18417        } else {
18418            // This case should hopefully never or seldom happen
18419            canvas = new Canvas(bitmap);
18420        }
18421        boolean enabledHwBitmapsInSwMode = canvas.isHwBitmapsInSwModeEnabled();
18422        canvas.setHwBitmapsInSwModeEnabled(true);
18423        if ((backgroundColor & 0xff000000) != 0) {
18424            bitmap.eraseColor(backgroundColor);
18425        }
18426
18427        computeScroll();
18428        final int restoreCount = canvas.save();
18429        canvas.scale(scale, scale);
18430        canvas.translate(-mScrollX, -mScrollY);
18431
18432        // Temporarily remove the dirty mask
18433        int flags = mPrivateFlags;
18434        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18435
18436        // Fast path for layouts with no backgrounds
18437        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18438            dispatchDraw(canvas);
18439            drawAutofilledHighlight(canvas);
18440            if (mOverlay != null && !mOverlay.isEmpty()) {
18441                mOverlay.getOverlayView().draw(canvas);
18442            }
18443        } else {
18444            draw(canvas);
18445        }
18446
18447        mPrivateFlags = flags;
18448
18449        canvas.restoreToCount(restoreCount);
18450        canvas.setBitmap(null);
18451        canvas.setHwBitmapsInSwModeEnabled(enabledHwBitmapsInSwMode);
18452
18453        if (attachInfo != null) {
18454            // Restore the cached Canvas for our siblings
18455            attachInfo.mCanvas = canvas;
18456        }
18457
18458        return bitmap;
18459    }
18460
18461    /**
18462     * Indicates whether this View is currently in edit mode. A View is usually
18463     * in edit mode when displayed within a developer tool. For instance, if
18464     * this View is being drawn by a visual user interface builder, this method
18465     * should return true.
18466     *
18467     * Subclasses should check the return value of this method to provide
18468     * different behaviors if their normal behavior might interfere with the
18469     * host environment. For instance: the class spawns a thread in its
18470     * constructor, the drawing code relies on device-specific features, etc.
18471     *
18472     * This method is usually checked in the drawing code of custom widgets.
18473     *
18474     * @return True if this View is in edit mode, false otherwise.
18475     */
18476    public boolean isInEditMode() {
18477        return false;
18478    }
18479
18480    /**
18481     * If the View draws content inside its padding and enables fading edges,
18482     * it needs to support padding offsets. Padding offsets are added to the
18483     * fading edges to extend the length of the fade so that it covers pixels
18484     * drawn inside the padding.
18485     *
18486     * Subclasses of this class should override this method if they need
18487     * to draw content inside the padding.
18488     *
18489     * @return True if padding offset must be applied, false otherwise.
18490     *
18491     * @see #getLeftPaddingOffset()
18492     * @see #getRightPaddingOffset()
18493     * @see #getTopPaddingOffset()
18494     * @see #getBottomPaddingOffset()
18495     *
18496     * @since CURRENT
18497     */
18498    protected boolean isPaddingOffsetRequired() {
18499        return false;
18500    }
18501
18502    /**
18503     * Amount by which to extend the left fading region. Called only when
18504     * {@link #isPaddingOffsetRequired()} returns true.
18505     *
18506     * @return The left padding offset in pixels.
18507     *
18508     * @see #isPaddingOffsetRequired()
18509     *
18510     * @since CURRENT
18511     */
18512    protected int getLeftPaddingOffset() {
18513        return 0;
18514    }
18515
18516    /**
18517     * Amount by which to extend the right fading region. Called only when
18518     * {@link #isPaddingOffsetRequired()} returns true.
18519     *
18520     * @return The right padding offset in pixels.
18521     *
18522     * @see #isPaddingOffsetRequired()
18523     *
18524     * @since CURRENT
18525     */
18526    protected int getRightPaddingOffset() {
18527        return 0;
18528    }
18529
18530    /**
18531     * Amount by which to extend the top fading region. Called only when
18532     * {@link #isPaddingOffsetRequired()} returns true.
18533     *
18534     * @return The top padding offset in pixels.
18535     *
18536     * @see #isPaddingOffsetRequired()
18537     *
18538     * @since CURRENT
18539     */
18540    protected int getTopPaddingOffset() {
18541        return 0;
18542    }
18543
18544    /**
18545     * Amount by which to extend the bottom fading region. Called only when
18546     * {@link #isPaddingOffsetRequired()} returns true.
18547     *
18548     * @return The bottom padding offset in pixels.
18549     *
18550     * @see #isPaddingOffsetRequired()
18551     *
18552     * @since CURRENT
18553     */
18554    protected int getBottomPaddingOffset() {
18555        return 0;
18556    }
18557
18558    /**
18559     * @hide
18560     * @param offsetRequired
18561     */
18562    protected int getFadeTop(boolean offsetRequired) {
18563        int top = mPaddingTop;
18564        if (offsetRequired) top += getTopPaddingOffset();
18565        return top;
18566    }
18567
18568    /**
18569     * @hide
18570     * @param offsetRequired
18571     */
18572    protected int getFadeHeight(boolean offsetRequired) {
18573        int padding = mPaddingTop;
18574        if (offsetRequired) padding += getTopPaddingOffset();
18575        return mBottom - mTop - mPaddingBottom - padding;
18576    }
18577
18578    /**
18579     * <p>Indicates whether this view is attached to a hardware accelerated
18580     * window or not.</p>
18581     *
18582     * <p>Even if this method returns true, it does not mean that every call
18583     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
18584     * accelerated {@link android.graphics.Canvas}. For instance, if this view
18585     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
18586     * window is hardware accelerated,
18587     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
18588     * return false, and this method will return true.</p>
18589     *
18590     * @return True if the view is attached to a window and the window is
18591     *         hardware accelerated; false in any other case.
18592     */
18593    @ViewDebug.ExportedProperty(category = "drawing")
18594    public boolean isHardwareAccelerated() {
18595        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
18596    }
18597
18598    /**
18599     * Sets a rectangular area on this view to which the view will be clipped
18600     * when it is drawn. Setting the value to null will remove the clip bounds
18601     * and the view will draw normally, using its full bounds.
18602     *
18603     * @param clipBounds The rectangular area, in the local coordinates of
18604     * this view, to which future drawing operations will be clipped.
18605     */
18606    public void setClipBounds(Rect clipBounds) {
18607        if (clipBounds == mClipBounds
18608                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
18609            return;
18610        }
18611        if (clipBounds != null) {
18612            if (mClipBounds == null) {
18613                mClipBounds = new Rect(clipBounds);
18614            } else {
18615                mClipBounds.set(clipBounds);
18616            }
18617        } else {
18618            mClipBounds = null;
18619        }
18620        mRenderNode.setClipBounds(mClipBounds);
18621        invalidateViewProperty(false, false);
18622    }
18623
18624    /**
18625     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
18626     *
18627     * @return A copy of the current clip bounds if clip bounds are set,
18628     * otherwise null.
18629     */
18630    public Rect getClipBounds() {
18631        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
18632    }
18633
18634
18635    /**
18636     * Populates an output rectangle with the clip bounds of the view,
18637     * returning {@code true} if successful or {@code false} if the view's
18638     * clip bounds are {@code null}.
18639     *
18640     * @param outRect rectangle in which to place the clip bounds of the view
18641     * @return {@code true} if successful or {@code false} if the view's
18642     *         clip bounds are {@code null}
18643     */
18644    public boolean getClipBounds(Rect outRect) {
18645        if (mClipBounds != null) {
18646            outRect.set(mClipBounds);
18647            return true;
18648        }
18649        return false;
18650    }
18651
18652    /**
18653     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
18654     * case of an active Animation being run on the view.
18655     */
18656    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
18657            Animation a, boolean scalingRequired) {
18658        Transformation invalidationTransform;
18659        final int flags = parent.mGroupFlags;
18660        final boolean initialized = a.isInitialized();
18661        if (!initialized) {
18662            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
18663            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
18664            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
18665            onAnimationStart();
18666        }
18667
18668        final Transformation t = parent.getChildTransformation();
18669        boolean more = a.getTransformation(drawingTime, t, 1f);
18670        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
18671            if (parent.mInvalidationTransformation == null) {
18672                parent.mInvalidationTransformation = new Transformation();
18673            }
18674            invalidationTransform = parent.mInvalidationTransformation;
18675            a.getTransformation(drawingTime, invalidationTransform, 1f);
18676        } else {
18677            invalidationTransform = t;
18678        }
18679
18680        if (more) {
18681            if (!a.willChangeBounds()) {
18682                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
18683                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
18684                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
18685                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
18686                    // The child need to draw an animation, potentially offscreen, so
18687                    // make sure we do not cancel invalidate requests
18688                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18689                    parent.invalidate(mLeft, mTop, mRight, mBottom);
18690                }
18691            } else {
18692                if (parent.mInvalidateRegion == null) {
18693                    parent.mInvalidateRegion = new RectF();
18694                }
18695                final RectF region = parent.mInvalidateRegion;
18696                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
18697                        invalidationTransform);
18698
18699                // The child need to draw an animation, potentially offscreen, so
18700                // make sure we do not cancel invalidate requests
18701                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
18702
18703                final int left = mLeft + (int) region.left;
18704                final int top = mTop + (int) region.top;
18705                parent.invalidate(left, top, left + (int) (region.width() + .5f),
18706                        top + (int) (region.height() + .5f));
18707            }
18708        }
18709        return more;
18710    }
18711
18712    /**
18713     * This method is called by getDisplayList() when a display list is recorded for a View.
18714     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
18715     */
18716    void setDisplayListProperties(RenderNode renderNode) {
18717        if (renderNode != null) {
18718            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
18719            renderNode.setClipToBounds(mParent instanceof ViewGroup
18720                    && ((ViewGroup) mParent).getClipChildren());
18721
18722            float alpha = 1;
18723            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
18724                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18725                ViewGroup parentVG = (ViewGroup) mParent;
18726                final Transformation t = parentVG.getChildTransformation();
18727                if (parentVG.getChildStaticTransformation(this, t)) {
18728                    final int transformType = t.getTransformationType();
18729                    if (transformType != Transformation.TYPE_IDENTITY) {
18730                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
18731                            alpha = t.getAlpha();
18732                        }
18733                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
18734                            renderNode.setStaticMatrix(t.getMatrix());
18735                        }
18736                    }
18737                }
18738            }
18739            if (mTransformationInfo != null) {
18740                alpha *= getFinalAlpha();
18741                if (alpha < 1) {
18742                    final int multipliedAlpha = (int) (255 * alpha);
18743                    if (onSetAlpha(multipliedAlpha)) {
18744                        alpha = 1;
18745                    }
18746                }
18747                renderNode.setAlpha(alpha);
18748            } else if (alpha < 1) {
18749                renderNode.setAlpha(alpha);
18750            }
18751        }
18752    }
18753
18754    /**
18755     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
18756     *
18757     * This is where the View specializes rendering behavior based on layer type,
18758     * and hardware acceleration.
18759     */
18760    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
18761        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
18762        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
18763         *
18764         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
18765         * HW accelerated, it can't handle drawing RenderNodes.
18766         */
18767        boolean drawingWithRenderNode = mAttachInfo != null
18768                && mAttachInfo.mHardwareAccelerated
18769                && hardwareAcceleratedCanvas;
18770
18771        boolean more = false;
18772        final boolean childHasIdentityMatrix = hasIdentityMatrix();
18773        final int parentFlags = parent.mGroupFlags;
18774
18775        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
18776            parent.getChildTransformation().clear();
18777            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18778        }
18779
18780        Transformation transformToApply = null;
18781        boolean concatMatrix = false;
18782        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
18783        final Animation a = getAnimation();
18784        if (a != null) {
18785            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
18786            concatMatrix = a.willChangeTransformationMatrix();
18787            if (concatMatrix) {
18788                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18789            }
18790            transformToApply = parent.getChildTransformation();
18791        } else {
18792            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
18793                // No longer animating: clear out old animation matrix
18794                mRenderNode.setAnimationMatrix(null);
18795                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
18796            }
18797            if (!drawingWithRenderNode
18798                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
18799                final Transformation t = parent.getChildTransformation();
18800                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
18801                if (hasTransform) {
18802                    final int transformType = t.getTransformationType();
18803                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
18804                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
18805                }
18806            }
18807        }
18808
18809        concatMatrix |= !childHasIdentityMatrix;
18810
18811        // Sets the flag as early as possible to allow draw() implementations
18812        // to call invalidate() successfully when doing animations
18813        mPrivateFlags |= PFLAG_DRAWN;
18814
18815        if (!concatMatrix &&
18816                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
18817                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
18818                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
18819                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
18820            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
18821            return more;
18822        }
18823        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
18824
18825        if (hardwareAcceleratedCanvas) {
18826            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
18827            // retain the flag's value temporarily in the mRecreateDisplayList flag
18828            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
18829            mPrivateFlags &= ~PFLAG_INVALIDATED;
18830        }
18831
18832        RenderNode renderNode = null;
18833        Bitmap cache = null;
18834        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
18835        if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
18836             if (layerType != LAYER_TYPE_NONE) {
18837                 // If not drawing with RenderNode, treat HW layers as SW
18838                 layerType = LAYER_TYPE_SOFTWARE;
18839                 buildDrawingCache(true);
18840            }
18841            cache = getDrawingCache(true);
18842        }
18843
18844        if (drawingWithRenderNode) {
18845            // Delay getting the display list until animation-driven alpha values are
18846            // set up and possibly passed on to the view
18847            renderNode = updateDisplayListIfDirty();
18848            if (!renderNode.isValid()) {
18849                // Uncommon, but possible. If a view is removed from the hierarchy during the call
18850                // to getDisplayList(), the display list will be marked invalid and we should not
18851                // try to use it again.
18852                renderNode = null;
18853                drawingWithRenderNode = false;
18854            }
18855        }
18856
18857        int sx = 0;
18858        int sy = 0;
18859        if (!drawingWithRenderNode) {
18860            computeScroll();
18861            sx = mScrollX;
18862            sy = mScrollY;
18863        }
18864
18865        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
18866        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
18867
18868        int restoreTo = -1;
18869        if (!drawingWithRenderNode || transformToApply != null) {
18870            restoreTo = canvas.save();
18871        }
18872        if (offsetForScroll) {
18873            canvas.translate(mLeft - sx, mTop - sy);
18874        } else {
18875            if (!drawingWithRenderNode) {
18876                canvas.translate(mLeft, mTop);
18877            }
18878            if (scalingRequired) {
18879                if (drawingWithRenderNode) {
18880                    // TODO: Might not need this if we put everything inside the DL
18881                    restoreTo = canvas.save();
18882                }
18883                // mAttachInfo cannot be null, otherwise scalingRequired == false
18884                final float scale = 1.0f / mAttachInfo.mApplicationScale;
18885                canvas.scale(scale, scale);
18886            }
18887        }
18888
18889        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
18890        if (transformToApply != null
18891                || alpha < 1
18892                || !hasIdentityMatrix()
18893                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18894            if (transformToApply != null || !childHasIdentityMatrix) {
18895                int transX = 0;
18896                int transY = 0;
18897
18898                if (offsetForScroll) {
18899                    transX = -sx;
18900                    transY = -sy;
18901                }
18902
18903                if (transformToApply != null) {
18904                    if (concatMatrix) {
18905                        if (drawingWithRenderNode) {
18906                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
18907                        } else {
18908                            // Undo the scroll translation, apply the transformation matrix,
18909                            // then redo the scroll translate to get the correct result.
18910                            canvas.translate(-transX, -transY);
18911                            canvas.concat(transformToApply.getMatrix());
18912                            canvas.translate(transX, transY);
18913                        }
18914                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18915                    }
18916
18917                    float transformAlpha = transformToApply.getAlpha();
18918                    if (transformAlpha < 1) {
18919                        alpha *= transformAlpha;
18920                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18921                    }
18922                }
18923
18924                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
18925                    canvas.translate(-transX, -transY);
18926                    canvas.concat(getMatrix());
18927                    canvas.translate(transX, transY);
18928                }
18929            }
18930
18931            // Deal with alpha if it is or used to be <1
18932            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
18933                if (alpha < 1) {
18934                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18935                } else {
18936                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
18937                }
18938                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
18939                if (!drawingWithDrawingCache) {
18940                    final int multipliedAlpha = (int) (255 * alpha);
18941                    if (!onSetAlpha(multipliedAlpha)) {
18942                        if (drawingWithRenderNode) {
18943                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
18944                        } else if (layerType == LAYER_TYPE_NONE) {
18945                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
18946                                    multipliedAlpha);
18947                        }
18948                    } else {
18949                        // Alpha is handled by the child directly, clobber the layer's alpha
18950                        mPrivateFlags |= PFLAG_ALPHA_SET;
18951                    }
18952                }
18953            }
18954        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
18955            onSetAlpha(255);
18956            mPrivateFlags &= ~PFLAG_ALPHA_SET;
18957        }
18958
18959        if (!drawingWithRenderNode) {
18960            // apply clips directly, since RenderNode won't do it for this draw
18961            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
18962                if (offsetForScroll) {
18963                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
18964                } else {
18965                    if (!scalingRequired || cache == null) {
18966                        canvas.clipRect(0, 0, getWidth(), getHeight());
18967                    } else {
18968                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
18969                    }
18970                }
18971            }
18972
18973            if (mClipBounds != null) {
18974                // clip bounds ignore scroll
18975                canvas.clipRect(mClipBounds);
18976            }
18977        }
18978
18979        if (!drawingWithDrawingCache) {
18980            if (drawingWithRenderNode) {
18981                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18982                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
18983            } else {
18984                // Fast path for layouts with no backgrounds
18985                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
18986                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18987                    dispatchDraw(canvas);
18988                } else {
18989                    draw(canvas);
18990                }
18991            }
18992        } else if (cache != null) {
18993            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
18994            if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
18995                // no layer paint, use temporary paint to draw bitmap
18996                Paint cachePaint = parent.mCachePaint;
18997                if (cachePaint == null) {
18998                    cachePaint = new Paint();
18999                    cachePaint.setDither(false);
19000                    parent.mCachePaint = cachePaint;
19001                }
19002                cachePaint.setAlpha((int) (alpha * 255));
19003                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
19004            } else {
19005                // use layer paint to draw the bitmap, merging the two alphas, but also restore
19006                int layerPaintAlpha = mLayerPaint.getAlpha();
19007                if (alpha < 1) {
19008                    mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
19009                }
19010                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
19011                if (alpha < 1) {
19012                    mLayerPaint.setAlpha(layerPaintAlpha);
19013                }
19014            }
19015        }
19016
19017        if (restoreTo >= 0) {
19018            canvas.restoreToCount(restoreTo);
19019        }
19020
19021        if (a != null && !more) {
19022            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
19023                onSetAlpha(255);
19024            }
19025            parent.finishAnimatingView(this, a);
19026        }
19027
19028        if (more && hardwareAcceleratedCanvas) {
19029            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
19030                // alpha animations should cause the child to recreate its display list
19031                invalidate(true);
19032            }
19033        }
19034
19035        mRecreateDisplayList = false;
19036
19037        return more;
19038    }
19039
19040    static Paint getDebugPaint() {
19041        if (sDebugPaint == null) {
19042            sDebugPaint = new Paint();
19043            sDebugPaint.setAntiAlias(false);
19044        }
19045        return sDebugPaint;
19046    }
19047
19048    final int dipsToPixels(int dips) {
19049        float scale = getContext().getResources().getDisplayMetrics().density;
19050        return (int) (dips * scale + 0.5f);
19051    }
19052
19053    final private void debugDrawFocus(Canvas canvas) {
19054        if (isFocused()) {
19055            final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP);
19056            final int l = mScrollX;
19057            final int r = l + mRight - mLeft;
19058            final int t = mScrollY;
19059            final int b = t + mBottom - mTop;
19060
19061            final Paint paint = getDebugPaint();
19062            paint.setColor(DEBUG_CORNERS_COLOR);
19063
19064            // Draw squares in corners.
19065            paint.setStyle(Paint.Style.FILL);
19066            canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint);
19067            canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint);
19068            canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint);
19069            canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint);
19070
19071            // Draw big X across the view.
19072            paint.setStyle(Paint.Style.STROKE);
19073            canvas.drawLine(l, t, r, b, paint);
19074            canvas.drawLine(l, b, r, t, paint);
19075        }
19076    }
19077
19078    /**
19079     * Manually render this view (and all of its children) to the given Canvas.
19080     * The view must have already done a full layout before this function is
19081     * called.  When implementing a view, implement
19082     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
19083     * If you do need to override this method, call the superclass version.
19084     *
19085     * @param canvas The Canvas to which the View is rendered.
19086     */
19087    @CallSuper
19088    public void draw(Canvas canvas) {
19089        final int privateFlags = mPrivateFlags;
19090        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
19091                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
19092        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
19093
19094        /*
19095         * Draw traversal performs several drawing steps which must be executed
19096         * in the appropriate order:
19097         *
19098         *      1. Draw the background
19099         *      2. If necessary, save the canvas' layers to prepare for fading
19100         *      3. Draw view's content
19101         *      4. Draw children
19102         *      5. If necessary, draw the fading edges and restore layers
19103         *      6. Draw decorations (scrollbars for instance)
19104         */
19105
19106        // Step 1, draw the background, if needed
19107        int saveCount;
19108
19109        if (!dirtyOpaque) {
19110            drawBackground(canvas);
19111        }
19112
19113        // skip step 2 & 5 if possible (common case)
19114        final int viewFlags = mViewFlags;
19115        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
19116        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
19117        if (!verticalEdges && !horizontalEdges) {
19118            // Step 3, draw the content
19119            if (!dirtyOpaque) onDraw(canvas);
19120
19121            // Step 4, draw the children
19122            dispatchDraw(canvas);
19123
19124            drawAutofilledHighlight(canvas);
19125
19126            // Overlay is part of the content and draws beneath Foreground
19127            if (mOverlay != null && !mOverlay.isEmpty()) {
19128                mOverlay.getOverlayView().dispatchDraw(canvas);
19129            }
19130
19131            // Step 6, draw decorations (foreground, scrollbars)
19132            onDrawForeground(canvas);
19133
19134            // Step 7, draw the default focus highlight
19135            drawDefaultFocusHighlight(canvas);
19136
19137            if (debugDraw()) {
19138                debugDrawFocus(canvas);
19139            }
19140
19141            // we're done...
19142            return;
19143        }
19144
19145        /*
19146         * Here we do the full fledged routine...
19147         * (this is an uncommon case where speed matters less,
19148         * this is why we repeat some of the tests that have been
19149         * done above)
19150         */
19151
19152        boolean drawTop = false;
19153        boolean drawBottom = false;
19154        boolean drawLeft = false;
19155        boolean drawRight = false;
19156
19157        float topFadeStrength = 0.0f;
19158        float bottomFadeStrength = 0.0f;
19159        float leftFadeStrength = 0.0f;
19160        float rightFadeStrength = 0.0f;
19161
19162        // Step 2, save the canvas' layers
19163        int paddingLeft = mPaddingLeft;
19164
19165        final boolean offsetRequired = isPaddingOffsetRequired();
19166        if (offsetRequired) {
19167            paddingLeft += getLeftPaddingOffset();
19168        }
19169
19170        int left = mScrollX + paddingLeft;
19171        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
19172        int top = mScrollY + getFadeTop(offsetRequired);
19173        int bottom = top + getFadeHeight(offsetRequired);
19174
19175        if (offsetRequired) {
19176            right += getRightPaddingOffset();
19177            bottom += getBottomPaddingOffset();
19178        }
19179
19180        final ScrollabilityCache scrollabilityCache = mScrollCache;
19181        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
19182        int length = (int) fadeHeight;
19183
19184        // clip the fade length if top and bottom fades overlap
19185        // overlapping fades produce odd-looking artifacts
19186        if (verticalEdges && (top + length > bottom - length)) {
19187            length = (bottom - top) / 2;
19188        }
19189
19190        // also clip horizontal fades if necessary
19191        if (horizontalEdges && (left + length > right - length)) {
19192            length = (right - left) / 2;
19193        }
19194
19195        if (verticalEdges) {
19196            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
19197            drawTop = topFadeStrength * fadeHeight > 1.0f;
19198            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
19199            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
19200        }
19201
19202        if (horizontalEdges) {
19203            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
19204            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
19205            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
19206            drawRight = rightFadeStrength * fadeHeight > 1.0f;
19207        }
19208
19209        saveCount = canvas.getSaveCount();
19210
19211        int solidColor = getSolidColor();
19212        if (solidColor == 0) {
19213            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
19214
19215            if (drawTop) {
19216                canvas.saveLayer(left, top, right, top + length, null, flags);
19217            }
19218
19219            if (drawBottom) {
19220                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
19221            }
19222
19223            if (drawLeft) {
19224                canvas.saveLayer(left, top, left + length, bottom, null, flags);
19225            }
19226
19227            if (drawRight) {
19228                canvas.saveLayer(right - length, top, right, bottom, null, flags);
19229            }
19230        } else {
19231            scrollabilityCache.setFadeColor(solidColor);
19232        }
19233
19234        // Step 3, draw the content
19235        if (!dirtyOpaque) onDraw(canvas);
19236
19237        // Step 4, draw the children
19238        dispatchDraw(canvas);
19239
19240        // Step 5, draw the fade effect and restore layers
19241        final Paint p = scrollabilityCache.paint;
19242        final Matrix matrix = scrollabilityCache.matrix;
19243        final Shader fade = scrollabilityCache.shader;
19244
19245        if (drawTop) {
19246            matrix.setScale(1, fadeHeight * topFadeStrength);
19247            matrix.postTranslate(left, top);
19248            fade.setLocalMatrix(matrix);
19249            p.setShader(fade);
19250            canvas.drawRect(left, top, right, top + length, p);
19251        }
19252
19253        if (drawBottom) {
19254            matrix.setScale(1, fadeHeight * bottomFadeStrength);
19255            matrix.postRotate(180);
19256            matrix.postTranslate(left, bottom);
19257            fade.setLocalMatrix(matrix);
19258            p.setShader(fade);
19259            canvas.drawRect(left, bottom - length, right, bottom, p);
19260        }
19261
19262        if (drawLeft) {
19263            matrix.setScale(1, fadeHeight * leftFadeStrength);
19264            matrix.postRotate(-90);
19265            matrix.postTranslate(left, top);
19266            fade.setLocalMatrix(matrix);
19267            p.setShader(fade);
19268            canvas.drawRect(left, top, left + length, bottom, p);
19269        }
19270
19271        if (drawRight) {
19272            matrix.setScale(1, fadeHeight * rightFadeStrength);
19273            matrix.postRotate(90);
19274            matrix.postTranslate(right, top);
19275            fade.setLocalMatrix(matrix);
19276            p.setShader(fade);
19277            canvas.drawRect(right - length, top, right, bottom, p);
19278        }
19279
19280        canvas.restoreToCount(saveCount);
19281
19282        drawAutofilledHighlight(canvas);
19283
19284        // Overlay is part of the content and draws beneath Foreground
19285        if (mOverlay != null && !mOverlay.isEmpty()) {
19286            mOverlay.getOverlayView().dispatchDraw(canvas);
19287        }
19288
19289        // Step 6, draw decorations (foreground, scrollbars)
19290        onDrawForeground(canvas);
19291
19292        if (debugDraw()) {
19293            debugDrawFocus(canvas);
19294        }
19295    }
19296
19297    /**
19298     * Draws the background onto the specified canvas.
19299     *
19300     * @param canvas Canvas on which to draw the background
19301     */
19302    private void drawBackground(Canvas canvas) {
19303        final Drawable background = mBackground;
19304        if (background == null) {
19305            return;
19306        }
19307
19308        setBackgroundBounds();
19309
19310        // Attempt to use a display list if requested.
19311        if (canvas.isHardwareAccelerated() && mAttachInfo != null
19312                && mAttachInfo.mThreadedRenderer != null) {
19313            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
19314
19315            final RenderNode renderNode = mBackgroundRenderNode;
19316            if (renderNode != null && renderNode.isValid()) {
19317                setBackgroundRenderNodeProperties(renderNode);
19318                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
19319                return;
19320            }
19321        }
19322
19323        final int scrollX = mScrollX;
19324        final int scrollY = mScrollY;
19325        if ((scrollX | scrollY) == 0) {
19326            background.draw(canvas);
19327        } else {
19328            canvas.translate(scrollX, scrollY);
19329            background.draw(canvas);
19330            canvas.translate(-scrollX, -scrollY);
19331        }
19332    }
19333
19334    /**
19335     * Sets the correct background bounds and rebuilds the outline, if needed.
19336     * <p/>
19337     * This is called by LayoutLib.
19338     */
19339    void setBackgroundBounds() {
19340        if (mBackgroundSizeChanged && mBackground != null) {
19341            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
19342            mBackgroundSizeChanged = false;
19343            rebuildOutline();
19344        }
19345    }
19346
19347    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
19348        renderNode.setTranslationX(mScrollX);
19349        renderNode.setTranslationY(mScrollY);
19350    }
19351
19352    /**
19353     * Creates a new display list or updates the existing display list for the
19354     * specified Drawable.
19355     *
19356     * @param drawable Drawable for which to create a display list
19357     * @param renderNode Existing RenderNode, or {@code null}
19358     * @return A valid display list for the specified drawable
19359     */
19360    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
19361        if (renderNode == null) {
19362            renderNode = RenderNode.create(drawable.getClass().getName(), this);
19363        }
19364
19365        final Rect bounds = drawable.getBounds();
19366        final int width = bounds.width();
19367        final int height = bounds.height();
19368        final DisplayListCanvas canvas = renderNode.start(width, height);
19369
19370        // Reverse left/top translation done by drawable canvas, which will
19371        // instead be applied by rendernode's LTRB bounds below. This way, the
19372        // drawable's bounds match with its rendernode bounds and its content
19373        // will lie within those bounds in the rendernode tree.
19374        canvas.translate(-bounds.left, -bounds.top);
19375
19376        try {
19377            drawable.draw(canvas);
19378        } finally {
19379            renderNode.end(canvas);
19380        }
19381
19382        // Set up drawable properties that are view-independent.
19383        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
19384        renderNode.setProjectBackwards(drawable.isProjected());
19385        renderNode.setProjectionReceiver(true);
19386        renderNode.setClipToBounds(false);
19387        return renderNode;
19388    }
19389
19390    /**
19391     * Returns the overlay for this view, creating it if it does not yet exist.
19392     * Adding drawables to the overlay will cause them to be displayed whenever
19393     * the view itself is redrawn. Objects in the overlay should be actively
19394     * managed: remove them when they should not be displayed anymore. The
19395     * overlay will always have the same size as its host view.
19396     *
19397     * <p>Note: Overlays do not currently work correctly with {@link
19398     * SurfaceView} or {@link TextureView}; contents in overlays for these
19399     * types of views may not display correctly.</p>
19400     *
19401     * @return The ViewOverlay object for this view.
19402     * @see ViewOverlay
19403     */
19404    public ViewOverlay getOverlay() {
19405        if (mOverlay == null) {
19406            mOverlay = new ViewOverlay(mContext, this);
19407        }
19408        return mOverlay;
19409    }
19410
19411    /**
19412     * Override this if your view is known to always be drawn on top of a solid color background,
19413     * and needs to draw fading edges. Returning a non-zero color enables the view system to
19414     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
19415     * should be set to 0xFF.
19416     *
19417     * @see #setVerticalFadingEdgeEnabled(boolean)
19418     * @see #setHorizontalFadingEdgeEnabled(boolean)
19419     *
19420     * @return The known solid color background for this view, or 0 if the color may vary
19421     */
19422    @ViewDebug.ExportedProperty(category = "drawing")
19423    @ColorInt
19424    public int getSolidColor() {
19425        return 0;
19426    }
19427
19428    /**
19429     * Build a human readable string representation of the specified view flags.
19430     *
19431     * @param flags the view flags to convert to a string
19432     * @return a String representing the supplied flags
19433     */
19434    private static String printFlags(int flags) {
19435        String output = "";
19436        int numFlags = 0;
19437        if ((flags & FOCUSABLE) == FOCUSABLE) {
19438            output += "TAKES_FOCUS";
19439            numFlags++;
19440        }
19441
19442        switch (flags & VISIBILITY_MASK) {
19443        case INVISIBLE:
19444            if (numFlags > 0) {
19445                output += " ";
19446            }
19447            output += "INVISIBLE";
19448            // USELESS HERE numFlags++;
19449            break;
19450        case GONE:
19451            if (numFlags > 0) {
19452                output += " ";
19453            }
19454            output += "GONE";
19455            // USELESS HERE numFlags++;
19456            break;
19457        default:
19458            break;
19459        }
19460        return output;
19461    }
19462
19463    /**
19464     * Build a human readable string representation of the specified private
19465     * view flags.
19466     *
19467     * @param privateFlags the private view flags to convert to a string
19468     * @return a String representing the supplied flags
19469     */
19470    private static String printPrivateFlags(int privateFlags) {
19471        String output = "";
19472        int numFlags = 0;
19473
19474        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
19475            output += "WANTS_FOCUS";
19476            numFlags++;
19477        }
19478
19479        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
19480            if (numFlags > 0) {
19481                output += " ";
19482            }
19483            output += "FOCUSED";
19484            numFlags++;
19485        }
19486
19487        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
19488            if (numFlags > 0) {
19489                output += " ";
19490            }
19491            output += "SELECTED";
19492            numFlags++;
19493        }
19494
19495        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
19496            if (numFlags > 0) {
19497                output += " ";
19498            }
19499            output += "IS_ROOT_NAMESPACE";
19500            numFlags++;
19501        }
19502
19503        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
19504            if (numFlags > 0) {
19505                output += " ";
19506            }
19507            output += "HAS_BOUNDS";
19508            numFlags++;
19509        }
19510
19511        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
19512            if (numFlags > 0) {
19513                output += " ";
19514            }
19515            output += "DRAWN";
19516            // USELESS HERE numFlags++;
19517        }
19518        return output;
19519    }
19520
19521    /**
19522     * <p>Indicates whether or not this view's layout will be requested during
19523     * the next hierarchy layout pass.</p>
19524     *
19525     * @return true if the layout will be forced during next layout pass
19526     */
19527    public boolean isLayoutRequested() {
19528        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19529    }
19530
19531    /**
19532     * Return true if o is a ViewGroup that is laying out using optical bounds.
19533     * @hide
19534     */
19535    public static boolean isLayoutModeOptical(Object o) {
19536        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
19537    }
19538
19539    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
19540        Insets parentInsets = mParent instanceof View ?
19541                ((View) mParent).getOpticalInsets() : Insets.NONE;
19542        Insets childInsets = getOpticalInsets();
19543        return setFrame(
19544                left   + parentInsets.left - childInsets.left,
19545                top    + parentInsets.top  - childInsets.top,
19546                right  + parentInsets.left + childInsets.right,
19547                bottom + parentInsets.top  + childInsets.bottom);
19548    }
19549
19550    /**
19551     * Assign a size and position to a view and all of its
19552     * descendants
19553     *
19554     * <p>This is the second phase of the layout mechanism.
19555     * (The first is measuring). In this phase, each parent calls
19556     * layout on all of its children to position them.
19557     * This is typically done using the child measurements
19558     * that were stored in the measure pass().</p>
19559     *
19560     * <p>Derived classes should not override this method.
19561     * Derived classes with children should override
19562     * onLayout. In that method, they should
19563     * call layout on each of their children.</p>
19564     *
19565     * @param l Left position, relative to parent
19566     * @param t Top position, relative to parent
19567     * @param r Right position, relative to parent
19568     * @param b Bottom position, relative to parent
19569     */
19570    @SuppressWarnings({"unchecked"})
19571    public void layout(int l, int t, int r, int b) {
19572        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
19573            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
19574            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19575        }
19576
19577        int oldL = mLeft;
19578        int oldT = mTop;
19579        int oldB = mBottom;
19580        int oldR = mRight;
19581
19582        boolean changed = isLayoutModeOptical(mParent) ?
19583                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
19584
19585        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
19586            onLayout(changed, l, t, r, b);
19587
19588            if (shouldDrawRoundScrollbar()) {
19589                if(mRoundScrollbarRenderer == null) {
19590                    mRoundScrollbarRenderer = new RoundScrollbarRenderer(this);
19591                }
19592            } else {
19593                mRoundScrollbarRenderer = null;
19594            }
19595
19596            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
19597
19598            ListenerInfo li = mListenerInfo;
19599            if (li != null && li.mOnLayoutChangeListeners != null) {
19600                ArrayList<OnLayoutChangeListener> listenersCopy =
19601                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
19602                int numListeners = listenersCopy.size();
19603                for (int i = 0; i < numListeners; ++i) {
19604                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
19605                }
19606            }
19607        }
19608
19609        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
19610        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
19611
19612        if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) {
19613            mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
19614            notifyEnterOrExitForAutoFillIfNeeded(true);
19615        }
19616    }
19617
19618    /**
19619     * Called from layout when this view should
19620     * assign a size and position to each of its children.
19621     *
19622     * Derived classes with children should override
19623     * this method and call layout on each of
19624     * their children.
19625     * @param changed This is a new size or position for this view
19626     * @param left Left position, relative to parent
19627     * @param top Top position, relative to parent
19628     * @param right Right position, relative to parent
19629     * @param bottom Bottom position, relative to parent
19630     */
19631    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
19632    }
19633
19634    /**
19635     * Assign a size and position to this view.
19636     *
19637     * This is called from layout.
19638     *
19639     * @param left Left position, relative to parent
19640     * @param top Top position, relative to parent
19641     * @param right Right position, relative to parent
19642     * @param bottom Bottom position, relative to parent
19643     * @return true if the new size and position are different than the
19644     *         previous ones
19645     * {@hide}
19646     */
19647    protected boolean setFrame(int left, int top, int right, int bottom) {
19648        boolean changed = false;
19649
19650        if (DBG) {
19651            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
19652                    + right + "," + bottom + ")");
19653        }
19654
19655        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
19656            changed = true;
19657
19658            // Remember our drawn bit
19659            int drawn = mPrivateFlags & PFLAG_DRAWN;
19660
19661            int oldWidth = mRight - mLeft;
19662            int oldHeight = mBottom - mTop;
19663            int newWidth = right - left;
19664            int newHeight = bottom - top;
19665            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
19666
19667            // Invalidate our old position
19668            invalidate(sizeChanged);
19669
19670            mLeft = left;
19671            mTop = top;
19672            mRight = right;
19673            mBottom = bottom;
19674            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
19675
19676            mPrivateFlags |= PFLAG_HAS_BOUNDS;
19677
19678
19679            if (sizeChanged) {
19680                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
19681            }
19682
19683            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
19684                // If we are visible, force the DRAWN bit to on so that
19685                // this invalidate will go through (at least to our parent).
19686                // This is because someone may have invalidated this view
19687                // before this call to setFrame came in, thereby clearing
19688                // the DRAWN bit.
19689                mPrivateFlags |= PFLAG_DRAWN;
19690                invalidate(sizeChanged);
19691                // parent display list may need to be recreated based on a change in the bounds
19692                // of any child
19693                invalidateParentCaches();
19694            }
19695
19696            // Reset drawn bit to original value (invalidate turns it off)
19697            mPrivateFlags |= drawn;
19698
19699            mBackgroundSizeChanged = true;
19700            mDefaultFocusHighlightSizeChanged = true;
19701            if (mForegroundInfo != null) {
19702                mForegroundInfo.mBoundsChanged = true;
19703            }
19704
19705            notifySubtreeAccessibilityStateChangedIfNeeded();
19706        }
19707        return changed;
19708    }
19709
19710    /**
19711     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
19712     * @hide
19713     */
19714    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
19715        setFrame(left, top, right, bottom);
19716    }
19717
19718    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
19719        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
19720        if (mOverlay != null) {
19721            mOverlay.getOverlayView().setRight(newWidth);
19722            mOverlay.getOverlayView().setBottom(newHeight);
19723        }
19724        rebuildOutline();
19725    }
19726
19727    /**
19728     * Finalize inflating a view from XML.  This is called as the last phase
19729     * of inflation, after all child views have been added.
19730     *
19731     * <p>Even if the subclass overrides onFinishInflate, they should always be
19732     * sure to call the super method, so that we get called.
19733     */
19734    @CallSuper
19735    protected void onFinishInflate() {
19736    }
19737
19738    /**
19739     * Returns the resources associated with this view.
19740     *
19741     * @return Resources object.
19742     */
19743    public Resources getResources() {
19744        return mResources;
19745    }
19746
19747    /**
19748     * Invalidates the specified Drawable.
19749     *
19750     * @param drawable the drawable to invalidate
19751     */
19752    @Override
19753    public void invalidateDrawable(@NonNull Drawable drawable) {
19754        if (verifyDrawable(drawable)) {
19755            final Rect dirty = drawable.getDirtyBounds();
19756            final int scrollX = mScrollX;
19757            final int scrollY = mScrollY;
19758
19759            invalidate(dirty.left + scrollX, dirty.top + scrollY,
19760                    dirty.right + scrollX, dirty.bottom + scrollY);
19761            rebuildOutline();
19762        }
19763    }
19764
19765    /**
19766     * Schedules an action on a drawable to occur at a specified time.
19767     *
19768     * @param who the recipient of the action
19769     * @param what the action to run on the drawable
19770     * @param when the time at which the action must occur. Uses the
19771     *        {@link SystemClock#uptimeMillis} timebase.
19772     */
19773    @Override
19774    public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
19775        if (verifyDrawable(who) && what != null) {
19776            final long delay = when - SystemClock.uptimeMillis();
19777            if (mAttachInfo != null) {
19778                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
19779                        Choreographer.CALLBACK_ANIMATION, what, who,
19780                        Choreographer.subtractFrameDelay(delay));
19781            } else {
19782                // Postpone the runnable until we know
19783                // on which thread it needs to run.
19784                getRunQueue().postDelayed(what, delay);
19785            }
19786        }
19787    }
19788
19789    /**
19790     * Cancels a scheduled action on a drawable.
19791     *
19792     * @param who the recipient of the action
19793     * @param what the action to cancel
19794     */
19795    @Override
19796    public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
19797        if (verifyDrawable(who) && what != null) {
19798            if (mAttachInfo != null) {
19799                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19800                        Choreographer.CALLBACK_ANIMATION, what, who);
19801            }
19802            getRunQueue().removeCallbacks(what);
19803        }
19804    }
19805
19806    /**
19807     * Unschedule any events associated with the given Drawable.  This can be
19808     * used when selecting a new Drawable into a view, so that the previous
19809     * one is completely unscheduled.
19810     *
19811     * @param who The Drawable to unschedule.
19812     *
19813     * @see #drawableStateChanged
19814     */
19815    public void unscheduleDrawable(Drawable who) {
19816        if (mAttachInfo != null && who != null) {
19817            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
19818                    Choreographer.CALLBACK_ANIMATION, null, who);
19819        }
19820    }
19821
19822    /**
19823     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
19824     * that the View directionality can and will be resolved before its Drawables.
19825     *
19826     * Will call {@link View#onResolveDrawables} when resolution is done.
19827     *
19828     * @hide
19829     */
19830    protected void resolveDrawables() {
19831        // Drawables resolution may need to happen before resolving the layout direction (which is
19832        // done only during the measure() call).
19833        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
19834        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
19835        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
19836        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
19837        // direction to be resolved as its resolved value will be the same as its raw value.
19838        if (!isLayoutDirectionResolved() &&
19839                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
19840            return;
19841        }
19842
19843        final int layoutDirection = isLayoutDirectionResolved() ?
19844                getLayoutDirection() : getRawLayoutDirection();
19845
19846        if (mBackground != null) {
19847            mBackground.setLayoutDirection(layoutDirection);
19848        }
19849        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19850            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
19851        }
19852        if (mDefaultFocusHighlight != null) {
19853            mDefaultFocusHighlight.setLayoutDirection(layoutDirection);
19854        }
19855        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
19856        onResolveDrawables(layoutDirection);
19857    }
19858
19859    boolean areDrawablesResolved() {
19860        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
19861    }
19862
19863    /**
19864     * Called when layout direction has been resolved.
19865     *
19866     * The default implementation does nothing.
19867     *
19868     * @param layoutDirection The resolved layout direction.
19869     *
19870     * @see #LAYOUT_DIRECTION_LTR
19871     * @see #LAYOUT_DIRECTION_RTL
19872     *
19873     * @hide
19874     */
19875    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
19876    }
19877
19878    /**
19879     * @hide
19880     */
19881    protected void resetResolvedDrawables() {
19882        resetResolvedDrawablesInternal();
19883    }
19884
19885    void resetResolvedDrawablesInternal() {
19886        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
19887    }
19888
19889    /**
19890     * If your view subclass is displaying its own Drawable objects, it should
19891     * override this function and return true for any Drawable it is
19892     * displaying.  This allows animations for those drawables to be
19893     * scheduled.
19894     *
19895     * <p>Be sure to call through to the super class when overriding this
19896     * function.
19897     *
19898     * @param who The Drawable to verify.  Return true if it is one you are
19899     *            displaying, else return the result of calling through to the
19900     *            super class.
19901     *
19902     * @return boolean If true than the Drawable is being displayed in the
19903     *         view; else false and it is not allowed to animate.
19904     *
19905     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
19906     * @see #drawableStateChanged()
19907     */
19908    @CallSuper
19909    protected boolean verifyDrawable(@NonNull Drawable who) {
19910        // Avoid verifying the scroll bar drawable so that we don't end up in
19911        // an invalidation loop. This effectively prevents the scroll bar
19912        // drawable from triggering invalidations and scheduling runnables.
19913        return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who)
19914                || (mDefaultFocusHighlight == who);
19915    }
19916
19917    /**
19918     * This function is called whenever the state of the view changes in such
19919     * a way that it impacts the state of drawables being shown.
19920     * <p>
19921     * If the View has a StateListAnimator, it will also be called to run necessary state
19922     * change animations.
19923     * <p>
19924     * Be sure to call through to the superclass when overriding this function.
19925     *
19926     * @see Drawable#setState(int[])
19927     */
19928    @CallSuper
19929    protected void drawableStateChanged() {
19930        final int[] state = getDrawableState();
19931        boolean changed = false;
19932
19933        final Drawable bg = mBackground;
19934        if (bg != null && bg.isStateful()) {
19935            changed |= bg.setState(state);
19936        }
19937
19938        final Drawable hl = mDefaultFocusHighlight;
19939        if (hl != null && hl.isStateful()) {
19940            changed |= hl.setState(state);
19941        }
19942
19943        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
19944        if (fg != null && fg.isStateful()) {
19945            changed |= fg.setState(state);
19946        }
19947
19948        if (mScrollCache != null) {
19949            final Drawable scrollBar = mScrollCache.scrollBar;
19950            if (scrollBar != null && scrollBar.isStateful()) {
19951                changed |= scrollBar.setState(state)
19952                        && mScrollCache.state != ScrollabilityCache.OFF;
19953            }
19954        }
19955
19956        if (mStateListAnimator != null) {
19957            mStateListAnimator.setState(state);
19958        }
19959
19960        if (changed) {
19961            invalidate();
19962        }
19963    }
19964
19965    /**
19966     * This function is called whenever the view hotspot changes and needs to
19967     * be propagated to drawables or child views managed by the view.
19968     * <p>
19969     * Dispatching to child views is handled by
19970     * {@link #dispatchDrawableHotspotChanged(float, float)}.
19971     * <p>
19972     * Be sure to call through to the superclass when overriding this function.
19973     *
19974     * @param x hotspot x coordinate
19975     * @param y hotspot y coordinate
19976     */
19977    @CallSuper
19978    public void drawableHotspotChanged(float x, float y) {
19979        if (mBackground != null) {
19980            mBackground.setHotspot(x, y);
19981        }
19982        if (mDefaultFocusHighlight != null) {
19983            mDefaultFocusHighlight.setHotspot(x, y);
19984        }
19985        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
19986            mForegroundInfo.mDrawable.setHotspot(x, y);
19987        }
19988
19989        dispatchDrawableHotspotChanged(x, y);
19990    }
19991
19992    /**
19993     * Dispatches drawableHotspotChanged to all of this View's children.
19994     *
19995     * @param x hotspot x coordinate
19996     * @param y hotspot y coordinate
19997     * @see #drawableHotspotChanged(float, float)
19998     */
19999    public void dispatchDrawableHotspotChanged(float x, float y) {
20000    }
20001
20002    /**
20003     * Call this to force a view to update its drawable state. This will cause
20004     * drawableStateChanged to be called on this view. Views that are interested
20005     * in the new state should call getDrawableState.
20006     *
20007     * @see #drawableStateChanged
20008     * @see #getDrawableState
20009     */
20010    public void refreshDrawableState() {
20011        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
20012        drawableStateChanged();
20013
20014        ViewParent parent = mParent;
20015        if (parent != null) {
20016            parent.childDrawableStateChanged(this);
20017        }
20018    }
20019
20020    /**
20021     * Create a default focus highlight if it doesn't exist.
20022     * @return a default focus highlight.
20023     */
20024    private Drawable getDefaultFocusHighlightDrawable() {
20025        if (mDefaultFocusHighlightCache == null) {
20026            if (mContext != null) {
20027                final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
20028                final TypedArray ta = mContext.obtainStyledAttributes(attrs);
20029                mDefaultFocusHighlightCache = ta.getDrawable(0);
20030                ta.recycle();
20031            }
20032        }
20033        return mDefaultFocusHighlightCache;
20034    }
20035
20036    /**
20037     * Set the current default focus highlight.
20038     * @param highlight the highlight drawable, or {@code null} if it's no longer needed.
20039     */
20040    private void setDefaultFocusHighlight(Drawable highlight) {
20041        mDefaultFocusHighlight = highlight;
20042        mDefaultFocusHighlightSizeChanged = true;
20043        if (highlight != null) {
20044            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20045                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20046            }
20047            highlight.setLayoutDirection(getLayoutDirection());
20048            if (highlight.isStateful()) {
20049                highlight.setState(getDrawableState());
20050            }
20051            if (isAttachedToWindow()) {
20052                highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20053            }
20054            // Set callback last, since the view may still be initializing.
20055            highlight.setCallback(this);
20056        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20057                && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20058            mPrivateFlags |= PFLAG_SKIP_DRAW;
20059        }
20060        invalidate();
20061    }
20062
20063    /**
20064     * Check whether we need to draw a default focus highlight when this view gets focused,
20065     * which requires:
20066     * <ul>
20067     *     <li>In both background and foreground, {@link android.R.attr#state_focused}
20068     *         is not defined.</li>
20069     *     <li>This view is not in touch mode.</li>
20070     *     <li>This view doesn't opt out for a default focus highlight, via
20071     *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
20072     *     <li>This view is attached to window.</li>
20073     * </ul>
20074     * @return {@code true} if a default focus highlight is needed.
20075     * @hide
20076     */
20077    @TestApi
20078    public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
20079        final boolean lackFocusState = (background == null || !background.isStateful()
20080                || !background.hasFocusStateSpecified())
20081                && (foreground == null || !foreground.isStateful()
20082                || !foreground.hasFocusStateSpecified());
20083        return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
20084                && isAttachedToWindow() && sUseDefaultFocusHighlight;
20085    }
20086
20087    /**
20088     * When this view is focused, switches on/off the default focused highlight.
20089     * <p>
20090     * This always happens when this view is focused, and only at this moment the default focus
20091     * highlight can be visible.
20092     */
20093    private void switchDefaultFocusHighlight() {
20094        if (isFocused()) {
20095            final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
20096                    mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
20097            final boolean active = mDefaultFocusHighlight != null;
20098            if (needed && !active) {
20099                setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
20100            } else if (!needed && active) {
20101                // The highlight is no longer needed, so tear it down.
20102                setDefaultFocusHighlight(null);
20103            }
20104        }
20105    }
20106
20107    /**
20108     * Draw the default focus highlight onto the canvas.
20109     * @param canvas the canvas where we're drawing the highlight.
20110     */
20111    private void drawDefaultFocusHighlight(Canvas canvas) {
20112        if (mDefaultFocusHighlight != null) {
20113            if (mDefaultFocusHighlightSizeChanged) {
20114                mDefaultFocusHighlightSizeChanged = false;
20115                final int l = mScrollX;
20116                final int r = l + mRight - mLeft;
20117                final int t = mScrollY;
20118                final int b = t + mBottom - mTop;
20119                mDefaultFocusHighlight.setBounds(l, t, r, b);
20120            }
20121            mDefaultFocusHighlight.draw(canvas);
20122        }
20123    }
20124
20125    /**
20126     * Return an array of resource IDs of the drawable states representing the
20127     * current state of the view.
20128     *
20129     * @return The current drawable state
20130     *
20131     * @see Drawable#setState(int[])
20132     * @see #drawableStateChanged()
20133     * @see #onCreateDrawableState(int)
20134     */
20135    public final int[] getDrawableState() {
20136        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
20137            return mDrawableState;
20138        } else {
20139            mDrawableState = onCreateDrawableState(0);
20140            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
20141            return mDrawableState;
20142        }
20143    }
20144
20145    /**
20146     * Generate the new {@link android.graphics.drawable.Drawable} state for
20147     * this view. This is called by the view
20148     * system when the cached Drawable state is determined to be invalid.  To
20149     * retrieve the current state, you should use {@link #getDrawableState}.
20150     *
20151     * @param extraSpace if non-zero, this is the number of extra entries you
20152     * would like in the returned array in which you can place your own
20153     * states.
20154     *
20155     * @return Returns an array holding the current {@link Drawable} state of
20156     * the view.
20157     *
20158     * @see #mergeDrawableStates(int[], int[])
20159     */
20160    protected int[] onCreateDrawableState(int extraSpace) {
20161        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
20162                mParent instanceof View) {
20163            return ((View) mParent).onCreateDrawableState(extraSpace);
20164        }
20165
20166        int[] drawableState;
20167
20168        int privateFlags = mPrivateFlags;
20169
20170        int viewStateIndex = 0;
20171        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
20172        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
20173        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
20174        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
20175        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
20176        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
20177        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
20178                ThreadedRenderer.isAvailable()) {
20179            // This is set if HW acceleration is requested, even if the current
20180            // process doesn't allow it.  This is just to allow app preview
20181            // windows to better match their app.
20182            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
20183        }
20184        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
20185
20186        final int privateFlags2 = mPrivateFlags2;
20187        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
20188            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
20189        }
20190        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
20191            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
20192        }
20193
20194        drawableState = StateSet.get(viewStateIndex);
20195
20196        //noinspection ConstantIfStatement
20197        if (false) {
20198            Log.i("View", "drawableStateIndex=" + viewStateIndex);
20199            Log.i("View", toString()
20200                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
20201                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
20202                    + " fo=" + hasFocus()
20203                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
20204                    + " wf=" + hasWindowFocus()
20205                    + ": " + Arrays.toString(drawableState));
20206        }
20207
20208        if (extraSpace == 0) {
20209            return drawableState;
20210        }
20211
20212        final int[] fullState;
20213        if (drawableState != null) {
20214            fullState = new int[drawableState.length + extraSpace];
20215            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
20216        } else {
20217            fullState = new int[extraSpace];
20218        }
20219
20220        return fullState;
20221    }
20222
20223    /**
20224     * Merge your own state values in <var>additionalState</var> into the base
20225     * state values <var>baseState</var> that were returned by
20226     * {@link #onCreateDrawableState(int)}.
20227     *
20228     * @param baseState The base state values returned by
20229     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
20230     * own additional state values.
20231     *
20232     * @param additionalState The additional state values you would like
20233     * added to <var>baseState</var>; this array is not modified.
20234     *
20235     * @return As a convenience, the <var>baseState</var> array you originally
20236     * passed into the function is returned.
20237     *
20238     * @see #onCreateDrawableState(int)
20239     */
20240    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
20241        final int N = baseState.length;
20242        int i = N - 1;
20243        while (i >= 0 && baseState[i] == 0) {
20244            i--;
20245        }
20246        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
20247        return baseState;
20248    }
20249
20250    /**
20251     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
20252     * on all Drawable objects associated with this view.
20253     * <p>
20254     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
20255     * attached to this view.
20256     */
20257    @CallSuper
20258    public void jumpDrawablesToCurrentState() {
20259        if (mBackground != null) {
20260            mBackground.jumpToCurrentState();
20261        }
20262        if (mStateListAnimator != null) {
20263            mStateListAnimator.jumpToCurrentState();
20264        }
20265        if (mDefaultFocusHighlight != null) {
20266            mDefaultFocusHighlight.jumpToCurrentState();
20267        }
20268        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
20269            mForegroundInfo.mDrawable.jumpToCurrentState();
20270        }
20271    }
20272
20273    /**
20274     * Sets the background color for this view.
20275     * @param color the color of the background
20276     */
20277    @RemotableViewMethod
20278    public void setBackgroundColor(@ColorInt int color) {
20279        if (mBackground instanceof ColorDrawable) {
20280            ((ColorDrawable) mBackground.mutate()).setColor(color);
20281            computeOpaqueFlags();
20282            mBackgroundResource = 0;
20283        } else {
20284            setBackground(new ColorDrawable(color));
20285        }
20286    }
20287
20288    /**
20289     * Set the background to a given resource. The resource should refer to
20290     * a Drawable object or 0 to remove the background.
20291     * @param resid The identifier of the resource.
20292     *
20293     * @attr ref android.R.styleable#View_background
20294     */
20295    @RemotableViewMethod
20296    public void setBackgroundResource(@DrawableRes int resid) {
20297        if (resid != 0 && resid == mBackgroundResource) {
20298            return;
20299        }
20300
20301        Drawable d = null;
20302        if (resid != 0) {
20303            d = mContext.getDrawable(resid);
20304        }
20305        setBackground(d);
20306
20307        mBackgroundResource = resid;
20308    }
20309
20310    /**
20311     * Set the background to a given Drawable, or remove the background. If the
20312     * background has padding, this View's padding is set to the background's
20313     * padding. However, when a background is removed, this View's padding isn't
20314     * touched. If setting the padding is desired, please use
20315     * {@link #setPadding(int, int, int, int)}.
20316     *
20317     * @param background The Drawable to use as the background, or null to remove the
20318     *        background
20319     */
20320    public void setBackground(Drawable background) {
20321        //noinspection deprecation
20322        setBackgroundDrawable(background);
20323    }
20324
20325    /**
20326     * @deprecated use {@link #setBackground(Drawable)} instead
20327     */
20328    @Deprecated
20329    public void setBackgroundDrawable(Drawable background) {
20330        computeOpaqueFlags();
20331
20332        if (background == mBackground) {
20333            return;
20334        }
20335
20336        boolean requestLayout = false;
20337
20338        mBackgroundResource = 0;
20339
20340        /*
20341         * Regardless of whether we're setting a new background or not, we want
20342         * to clear the previous drawable. setVisible first while we still have the callback set.
20343         */
20344        if (mBackground != null) {
20345            if (isAttachedToWindow()) {
20346                mBackground.setVisible(false, false);
20347            }
20348            mBackground.setCallback(null);
20349            unscheduleDrawable(mBackground);
20350        }
20351
20352        if (background != null) {
20353            Rect padding = sThreadLocal.get();
20354            if (padding == null) {
20355                padding = new Rect();
20356                sThreadLocal.set(padding);
20357            }
20358            resetResolvedDrawablesInternal();
20359            background.setLayoutDirection(getLayoutDirection());
20360            if (background.getPadding(padding)) {
20361                resetResolvedPaddingInternal();
20362                switch (background.getLayoutDirection()) {
20363                    case LAYOUT_DIRECTION_RTL:
20364                        mUserPaddingLeftInitial = padding.right;
20365                        mUserPaddingRightInitial = padding.left;
20366                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
20367                        break;
20368                    case LAYOUT_DIRECTION_LTR:
20369                    default:
20370                        mUserPaddingLeftInitial = padding.left;
20371                        mUserPaddingRightInitial = padding.right;
20372                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
20373                }
20374                mLeftPaddingDefined = false;
20375                mRightPaddingDefined = false;
20376            }
20377
20378            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
20379            // if it has a different minimum size, we should layout again
20380            if (mBackground == null
20381                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
20382                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
20383                requestLayout = true;
20384            }
20385
20386            // Set mBackground before we set this as the callback and start making other
20387            // background drawable state change calls. In particular, the setVisible call below
20388            // can result in drawables attempting to start animations or otherwise invalidate,
20389            // which requires the view set as the callback (us) to recognize the drawable as
20390            // belonging to it as per verifyDrawable.
20391            mBackground = background;
20392            if (background.isStateful()) {
20393                background.setState(getDrawableState());
20394            }
20395            if (isAttachedToWindow()) {
20396                background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20397            }
20398
20399            applyBackgroundTint();
20400
20401            // Set callback last, since the view may still be initializing.
20402            background.setCallback(this);
20403
20404            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20405                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20406                requestLayout = true;
20407            }
20408        } else {
20409            /* Remove the background */
20410            mBackground = null;
20411            if ((mViewFlags & WILL_NOT_DRAW) != 0
20412                    && (mDefaultFocusHighlight == null)
20413                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
20414                mPrivateFlags |= PFLAG_SKIP_DRAW;
20415            }
20416
20417            /*
20418             * When the background is set, we try to apply its padding to this
20419             * View. When the background is removed, we don't touch this View's
20420             * padding. This is noted in the Javadocs. Hence, we don't need to
20421             * requestLayout(), the invalidate() below is sufficient.
20422             */
20423
20424            // The old background's minimum size could have affected this
20425            // View's layout, so let's requestLayout
20426            requestLayout = true;
20427        }
20428
20429        computeOpaqueFlags();
20430
20431        if (requestLayout) {
20432            requestLayout();
20433        }
20434
20435        mBackgroundSizeChanged = true;
20436        invalidate(true);
20437        invalidateOutline();
20438    }
20439
20440    /**
20441     * Gets the background drawable
20442     *
20443     * @return The drawable used as the background for this view, if any.
20444     *
20445     * @see #setBackground(Drawable)
20446     *
20447     * @attr ref android.R.styleable#View_background
20448     */
20449    public Drawable getBackground() {
20450        return mBackground;
20451    }
20452
20453    /**
20454     * Applies a tint to the background drawable. Does not modify the current tint
20455     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20456     * <p>
20457     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
20458     * mutate the drawable and apply the specified tint and tint mode using
20459     * {@link Drawable#setTintList(ColorStateList)}.
20460     *
20461     * @param tint the tint to apply, may be {@code null} to clear tint
20462     *
20463     * @attr ref android.R.styleable#View_backgroundTint
20464     * @see #getBackgroundTintList()
20465     * @see Drawable#setTintList(ColorStateList)
20466     */
20467    public void setBackgroundTintList(@Nullable ColorStateList tint) {
20468        if (mBackgroundTint == null) {
20469            mBackgroundTint = new TintInfo();
20470        }
20471        mBackgroundTint.mTintList = tint;
20472        mBackgroundTint.mHasTintList = true;
20473
20474        applyBackgroundTint();
20475    }
20476
20477    /**
20478     * Return the tint applied to the background drawable, if specified.
20479     *
20480     * @return the tint applied to the background drawable
20481     * @attr ref android.R.styleable#View_backgroundTint
20482     * @see #setBackgroundTintList(ColorStateList)
20483     */
20484    @Nullable
20485    public ColorStateList getBackgroundTintList() {
20486        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
20487    }
20488
20489    /**
20490     * Specifies the blending mode used to apply the tint specified by
20491     * {@link #setBackgroundTintList(ColorStateList)}} to the background
20492     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20493     *
20494     * @param tintMode the blending mode used to apply the tint, may be
20495     *                 {@code null} to clear tint
20496     * @attr ref android.R.styleable#View_backgroundTintMode
20497     * @see #getBackgroundTintMode()
20498     * @see Drawable#setTintMode(PorterDuff.Mode)
20499     */
20500    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20501        if (mBackgroundTint == null) {
20502            mBackgroundTint = new TintInfo();
20503        }
20504        mBackgroundTint.mTintMode = tintMode;
20505        mBackgroundTint.mHasTintMode = true;
20506
20507        applyBackgroundTint();
20508    }
20509
20510    /**
20511     * Return the blending mode used to apply the tint to the background
20512     * drawable, if specified.
20513     *
20514     * @return the blending mode used to apply the tint to the background
20515     *         drawable
20516     * @attr ref android.R.styleable#View_backgroundTintMode
20517     * @see #setBackgroundTintMode(PorterDuff.Mode)
20518     */
20519    @Nullable
20520    public PorterDuff.Mode getBackgroundTintMode() {
20521        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
20522    }
20523
20524    private void applyBackgroundTint() {
20525        if (mBackground != null && mBackgroundTint != null) {
20526            final TintInfo tintInfo = mBackgroundTint;
20527            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20528                mBackground = mBackground.mutate();
20529
20530                if (tintInfo.mHasTintList) {
20531                    mBackground.setTintList(tintInfo.mTintList);
20532                }
20533
20534                if (tintInfo.mHasTintMode) {
20535                    mBackground.setTintMode(tintInfo.mTintMode);
20536                }
20537
20538                // The drawable (or one of its children) may not have been
20539                // stateful before applying the tint, so let's try again.
20540                if (mBackground.isStateful()) {
20541                    mBackground.setState(getDrawableState());
20542                }
20543            }
20544        }
20545    }
20546
20547    /**
20548     * Returns the drawable used as the foreground of this View. The
20549     * foreground drawable, if non-null, is always drawn on top of the view's content.
20550     *
20551     * @return a Drawable or null if no foreground was set
20552     *
20553     * @see #onDrawForeground(Canvas)
20554     */
20555    public Drawable getForeground() {
20556        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20557    }
20558
20559    /**
20560     * Supply a Drawable that is to be rendered on top of all of the content in the view.
20561     *
20562     * @param foreground the Drawable to be drawn on top of the children
20563     *
20564     * @attr ref android.R.styleable#View_foreground
20565     */
20566    public void setForeground(Drawable foreground) {
20567        if (mForegroundInfo == null) {
20568            if (foreground == null) {
20569                // Nothing to do.
20570                return;
20571            }
20572            mForegroundInfo = new ForegroundInfo();
20573        }
20574
20575        if (foreground == mForegroundInfo.mDrawable) {
20576            // Nothing to do
20577            return;
20578        }
20579
20580        if (mForegroundInfo.mDrawable != null) {
20581            if (isAttachedToWindow()) {
20582                mForegroundInfo.mDrawable.setVisible(false, false);
20583            }
20584            mForegroundInfo.mDrawable.setCallback(null);
20585            unscheduleDrawable(mForegroundInfo.mDrawable);
20586        }
20587
20588        mForegroundInfo.mDrawable = foreground;
20589        mForegroundInfo.mBoundsChanged = true;
20590        if (foreground != null) {
20591            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
20592                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
20593            }
20594            foreground.setLayoutDirection(getLayoutDirection());
20595            if (foreground.isStateful()) {
20596                foreground.setState(getDrawableState());
20597            }
20598            applyForegroundTint();
20599            if (isAttachedToWindow()) {
20600                foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
20601            }
20602            // Set callback last, since the view may still be initializing.
20603            foreground.setCallback(this);
20604        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null
20605                && (mDefaultFocusHighlight == null)) {
20606            mPrivateFlags |= PFLAG_SKIP_DRAW;
20607        }
20608        requestLayout();
20609        invalidate();
20610    }
20611
20612    /**
20613     * Magic bit used to support features of framework-internal window decor implementation details.
20614     * This used to live exclusively in FrameLayout.
20615     *
20616     * @return true if the foreground should draw inside the padding region or false
20617     *         if it should draw inset by the view's padding
20618     * @hide internal use only; only used by FrameLayout and internal screen layouts.
20619     */
20620    public boolean isForegroundInsidePadding() {
20621        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
20622    }
20623
20624    /**
20625     * Describes how the foreground is positioned.
20626     *
20627     * @return foreground gravity.
20628     *
20629     * @see #setForegroundGravity(int)
20630     *
20631     * @attr ref android.R.styleable#View_foregroundGravity
20632     */
20633    public int getForegroundGravity() {
20634        return mForegroundInfo != null ? mForegroundInfo.mGravity
20635                : Gravity.START | Gravity.TOP;
20636    }
20637
20638    /**
20639     * Describes how the foreground is positioned. Defaults to START and TOP.
20640     *
20641     * @param gravity see {@link android.view.Gravity}
20642     *
20643     * @see #getForegroundGravity()
20644     *
20645     * @attr ref android.R.styleable#View_foregroundGravity
20646     */
20647    public void setForegroundGravity(int gravity) {
20648        if (mForegroundInfo == null) {
20649            mForegroundInfo = new ForegroundInfo();
20650        }
20651
20652        if (mForegroundInfo.mGravity != gravity) {
20653            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
20654                gravity |= Gravity.START;
20655            }
20656
20657            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
20658                gravity |= Gravity.TOP;
20659            }
20660
20661            mForegroundInfo.mGravity = gravity;
20662            requestLayout();
20663        }
20664    }
20665
20666    /**
20667     * Applies a tint to the foreground drawable. Does not modify the current tint
20668     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
20669     * <p>
20670     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
20671     * mutate the drawable and apply the specified tint and tint mode using
20672     * {@link Drawable#setTintList(ColorStateList)}.
20673     *
20674     * @param tint the tint to apply, may be {@code null} to clear tint
20675     *
20676     * @attr ref android.R.styleable#View_foregroundTint
20677     * @see #getForegroundTintList()
20678     * @see Drawable#setTintList(ColorStateList)
20679     */
20680    public void setForegroundTintList(@Nullable ColorStateList tint) {
20681        if (mForegroundInfo == null) {
20682            mForegroundInfo = new ForegroundInfo();
20683        }
20684        if (mForegroundInfo.mTintInfo == null) {
20685            mForegroundInfo.mTintInfo = new TintInfo();
20686        }
20687        mForegroundInfo.mTintInfo.mTintList = tint;
20688        mForegroundInfo.mTintInfo.mHasTintList = true;
20689
20690        applyForegroundTint();
20691    }
20692
20693    /**
20694     * Return the tint applied to the foreground drawable, if specified.
20695     *
20696     * @return the tint applied to the foreground drawable
20697     * @attr ref android.R.styleable#View_foregroundTint
20698     * @see #setForegroundTintList(ColorStateList)
20699     */
20700    @Nullable
20701    public ColorStateList getForegroundTintList() {
20702        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20703                ? mForegroundInfo.mTintInfo.mTintList : null;
20704    }
20705
20706    /**
20707     * Specifies the blending mode used to apply the tint specified by
20708     * {@link #setForegroundTintList(ColorStateList)}} to the background
20709     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
20710     *
20711     * @param tintMode the blending mode used to apply the tint, may be
20712     *                 {@code null} to clear tint
20713     * @attr ref android.R.styleable#View_foregroundTintMode
20714     * @see #getForegroundTintMode()
20715     * @see Drawable#setTintMode(PorterDuff.Mode)
20716     */
20717    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
20718        if (mForegroundInfo == null) {
20719            mForegroundInfo = new ForegroundInfo();
20720        }
20721        if (mForegroundInfo.mTintInfo == null) {
20722            mForegroundInfo.mTintInfo = new TintInfo();
20723        }
20724        mForegroundInfo.mTintInfo.mTintMode = tintMode;
20725        mForegroundInfo.mTintInfo.mHasTintMode = true;
20726
20727        applyForegroundTint();
20728    }
20729
20730    /**
20731     * Return the blending mode used to apply the tint to the foreground
20732     * drawable, if specified.
20733     *
20734     * @return the blending mode used to apply the tint to the foreground
20735     *         drawable
20736     * @attr ref android.R.styleable#View_foregroundTintMode
20737     * @see #setForegroundTintMode(PorterDuff.Mode)
20738     */
20739    @Nullable
20740    public PorterDuff.Mode getForegroundTintMode() {
20741        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
20742                ? mForegroundInfo.mTintInfo.mTintMode : null;
20743    }
20744
20745    private void applyForegroundTint() {
20746        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
20747                && mForegroundInfo.mTintInfo != null) {
20748            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
20749            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
20750                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
20751
20752                if (tintInfo.mHasTintList) {
20753                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
20754                }
20755
20756                if (tintInfo.mHasTintMode) {
20757                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
20758                }
20759
20760                // The drawable (or one of its children) may not have been
20761                // stateful before applying the tint, so let's try again.
20762                if (mForegroundInfo.mDrawable.isStateful()) {
20763                    mForegroundInfo.mDrawable.setState(getDrawableState());
20764                }
20765            }
20766        }
20767    }
20768
20769    /**
20770     * Get the drawable to be overlayed when a view is autofilled
20771     *
20772     * @return The drawable
20773     *
20774     * @throws IllegalStateException if the drawable could not be found.
20775     */
20776    @Nullable private Drawable getAutofilledDrawable() {
20777        if (mAttachInfo == null) {
20778            return null;
20779        }
20780        // Lazily load the isAutofilled drawable.
20781        if (mAttachInfo.mAutofilledDrawable == null) {
20782            Context rootContext = getRootView().getContext();
20783            TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR);
20784            int attributeResourceId = a.getResourceId(0, 0);
20785            mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId);
20786            a.recycle();
20787        }
20788
20789        return mAttachInfo.mAutofilledDrawable;
20790    }
20791
20792    /**
20793     * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled.
20794     *
20795     * @param canvas The canvas to draw on
20796     */
20797    private void drawAutofilledHighlight(@NonNull Canvas canvas) {
20798        if (isAutofilled()) {
20799            Drawable autofilledHighlight = getAutofilledDrawable();
20800
20801            if (autofilledHighlight != null) {
20802                autofilledHighlight.setBounds(0, 0, getWidth(), getHeight());
20803                autofilledHighlight.draw(canvas);
20804            }
20805        }
20806    }
20807
20808    /**
20809     * Draw any foreground content for this view.
20810     *
20811     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
20812     * drawable or other view-specific decorations. The foreground is drawn on top of the
20813     * primary view content.</p>
20814     *
20815     * @param canvas canvas to draw into
20816     */
20817    public void onDrawForeground(Canvas canvas) {
20818        onDrawScrollIndicators(canvas);
20819        onDrawScrollBars(canvas);
20820
20821        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
20822        if (foreground != null) {
20823            if (mForegroundInfo.mBoundsChanged) {
20824                mForegroundInfo.mBoundsChanged = false;
20825                final Rect selfBounds = mForegroundInfo.mSelfBounds;
20826                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
20827
20828                if (mForegroundInfo.mInsidePadding) {
20829                    selfBounds.set(0, 0, getWidth(), getHeight());
20830                } else {
20831                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
20832                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
20833                }
20834
20835                final int ld = getLayoutDirection();
20836                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
20837                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
20838                foreground.setBounds(overlayBounds);
20839            }
20840
20841            foreground.draw(canvas);
20842        }
20843    }
20844
20845    /**
20846     * Sets the padding. The view may add on the space required to display
20847     * the scrollbars, depending on the style and visibility of the scrollbars.
20848     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
20849     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
20850     * from the values set in this call.
20851     *
20852     * @attr ref android.R.styleable#View_padding
20853     * @attr ref android.R.styleable#View_paddingBottom
20854     * @attr ref android.R.styleable#View_paddingLeft
20855     * @attr ref android.R.styleable#View_paddingRight
20856     * @attr ref android.R.styleable#View_paddingTop
20857     * @param left the left padding in pixels
20858     * @param top the top padding in pixels
20859     * @param right the right padding in pixels
20860     * @param bottom the bottom padding in pixels
20861     */
20862    public void setPadding(int left, int top, int right, int bottom) {
20863        resetResolvedPaddingInternal();
20864
20865        mUserPaddingStart = UNDEFINED_PADDING;
20866        mUserPaddingEnd = UNDEFINED_PADDING;
20867
20868        mUserPaddingLeftInitial = left;
20869        mUserPaddingRightInitial = right;
20870
20871        mLeftPaddingDefined = true;
20872        mRightPaddingDefined = true;
20873
20874        internalSetPadding(left, top, right, bottom);
20875    }
20876
20877    /**
20878     * @hide
20879     */
20880    protected void internalSetPadding(int left, int top, int right, int bottom) {
20881        mUserPaddingLeft = left;
20882        mUserPaddingRight = right;
20883        mUserPaddingBottom = bottom;
20884
20885        final int viewFlags = mViewFlags;
20886        boolean changed = false;
20887
20888        // Common case is there are no scroll bars.
20889        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
20890            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
20891                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
20892                        ? 0 : getVerticalScrollbarWidth();
20893                switch (mVerticalScrollbarPosition) {
20894                    case SCROLLBAR_POSITION_DEFAULT:
20895                        if (isLayoutRtl()) {
20896                            left += offset;
20897                        } else {
20898                            right += offset;
20899                        }
20900                        break;
20901                    case SCROLLBAR_POSITION_RIGHT:
20902                        right += offset;
20903                        break;
20904                    case SCROLLBAR_POSITION_LEFT:
20905                        left += offset;
20906                        break;
20907                }
20908            }
20909            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
20910                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
20911                        ? 0 : getHorizontalScrollbarHeight();
20912            }
20913        }
20914
20915        if (mPaddingLeft != left) {
20916            changed = true;
20917            mPaddingLeft = left;
20918        }
20919        if (mPaddingTop != top) {
20920            changed = true;
20921            mPaddingTop = top;
20922        }
20923        if (mPaddingRight != right) {
20924            changed = true;
20925            mPaddingRight = right;
20926        }
20927        if (mPaddingBottom != bottom) {
20928            changed = true;
20929            mPaddingBottom = bottom;
20930        }
20931
20932        if (changed) {
20933            requestLayout();
20934            invalidateOutline();
20935        }
20936    }
20937
20938    /**
20939     * Sets the relative padding. The view may add on the space required to display
20940     * the scrollbars, depending on the style and visibility of the scrollbars.
20941     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
20942     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
20943     * from the values set in this call.
20944     *
20945     * @attr ref android.R.styleable#View_padding
20946     * @attr ref android.R.styleable#View_paddingBottom
20947     * @attr ref android.R.styleable#View_paddingStart
20948     * @attr ref android.R.styleable#View_paddingEnd
20949     * @attr ref android.R.styleable#View_paddingTop
20950     * @param start the start padding in pixels
20951     * @param top the top padding in pixels
20952     * @param end the end padding in pixels
20953     * @param bottom the bottom padding in pixels
20954     */
20955    public void setPaddingRelative(int start, int top, int end, int bottom) {
20956        resetResolvedPaddingInternal();
20957
20958        mUserPaddingStart = start;
20959        mUserPaddingEnd = end;
20960        mLeftPaddingDefined = true;
20961        mRightPaddingDefined = true;
20962
20963        switch(getLayoutDirection()) {
20964            case LAYOUT_DIRECTION_RTL:
20965                mUserPaddingLeftInitial = end;
20966                mUserPaddingRightInitial = start;
20967                internalSetPadding(end, top, start, bottom);
20968                break;
20969            case LAYOUT_DIRECTION_LTR:
20970            default:
20971                mUserPaddingLeftInitial = start;
20972                mUserPaddingRightInitial = end;
20973                internalSetPadding(start, top, end, bottom);
20974        }
20975    }
20976
20977    /**
20978     * Returns the top padding of this view.
20979     *
20980     * @return the top padding in pixels
20981     */
20982    public int getPaddingTop() {
20983        return mPaddingTop;
20984    }
20985
20986    /**
20987     * Returns the bottom padding of this view. If there are inset and enabled
20988     * scrollbars, this value may include the space required to display the
20989     * scrollbars as well.
20990     *
20991     * @return the bottom padding in pixels
20992     */
20993    public int getPaddingBottom() {
20994        return mPaddingBottom;
20995    }
20996
20997    /**
20998     * Returns the left padding of this view. If there are inset and enabled
20999     * scrollbars, this value may include the space required to display the
21000     * scrollbars as well.
21001     *
21002     * @return the left padding in pixels
21003     */
21004    public int getPaddingLeft() {
21005        if (!isPaddingResolved()) {
21006            resolvePadding();
21007        }
21008        return mPaddingLeft;
21009    }
21010
21011    /**
21012     * Returns the start padding of this view depending on its resolved layout direction.
21013     * If there are inset and enabled scrollbars, this value may include the space
21014     * required to display the scrollbars as well.
21015     *
21016     * @return the start padding in pixels
21017     */
21018    public int getPaddingStart() {
21019        if (!isPaddingResolved()) {
21020            resolvePadding();
21021        }
21022        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
21023                mPaddingRight : mPaddingLeft;
21024    }
21025
21026    /**
21027     * Returns the right padding of this view. If there are inset and enabled
21028     * scrollbars, this value may include the space required to display the
21029     * scrollbars as well.
21030     *
21031     * @return the right padding in pixels
21032     */
21033    public int getPaddingRight() {
21034        if (!isPaddingResolved()) {
21035            resolvePadding();
21036        }
21037        return mPaddingRight;
21038    }
21039
21040    /**
21041     * Returns the end padding of this view depending on its resolved layout direction.
21042     * If there are inset and enabled scrollbars, this value may include the space
21043     * required to display the scrollbars as well.
21044     *
21045     * @return the end padding in pixels
21046     */
21047    public int getPaddingEnd() {
21048        if (!isPaddingResolved()) {
21049            resolvePadding();
21050        }
21051        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
21052                mPaddingLeft : mPaddingRight;
21053    }
21054
21055    /**
21056     * Return if the padding has been set through relative values
21057     * {@link #setPaddingRelative(int, int, int, int)} or through
21058     * @attr ref android.R.styleable#View_paddingStart or
21059     * @attr ref android.R.styleable#View_paddingEnd
21060     *
21061     * @return true if the padding is relative or false if it is not.
21062     */
21063    public boolean isPaddingRelative() {
21064        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
21065    }
21066
21067    Insets computeOpticalInsets() {
21068        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
21069    }
21070
21071    /**
21072     * @hide
21073     */
21074    public void resetPaddingToInitialValues() {
21075        if (isRtlCompatibilityMode()) {
21076            mPaddingLeft = mUserPaddingLeftInitial;
21077            mPaddingRight = mUserPaddingRightInitial;
21078            return;
21079        }
21080        if (isLayoutRtl()) {
21081            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
21082            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
21083        } else {
21084            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
21085            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
21086        }
21087    }
21088
21089    /**
21090     * @hide
21091     */
21092    public Insets getOpticalInsets() {
21093        if (mLayoutInsets == null) {
21094            mLayoutInsets = computeOpticalInsets();
21095        }
21096        return mLayoutInsets;
21097    }
21098
21099    /**
21100     * Set this view's optical insets.
21101     *
21102     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
21103     * property. Views that compute their own optical insets should call it as part of measurement.
21104     * This method does not request layout. If you are setting optical insets outside of
21105     * measure/layout itself you will want to call requestLayout() yourself.
21106     * </p>
21107     * @hide
21108     */
21109    public void setOpticalInsets(Insets insets) {
21110        mLayoutInsets = insets;
21111    }
21112
21113    /**
21114     * Changes the selection state of this view. A view can be selected or not.
21115     * Note that selection is not the same as focus. Views are typically
21116     * selected in the context of an AdapterView like ListView or GridView;
21117     * the selected view is the view that is highlighted.
21118     *
21119     * @param selected true if the view must be selected, false otherwise
21120     */
21121    public void setSelected(boolean selected) {
21122        //noinspection DoubleNegation
21123        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
21124            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
21125            if (!selected) resetPressedState();
21126            invalidate(true);
21127            refreshDrawableState();
21128            dispatchSetSelected(selected);
21129            if (selected) {
21130                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
21131            } else {
21132                notifyViewAccessibilityStateChangedIfNeeded(
21133                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
21134            }
21135        }
21136    }
21137
21138    /**
21139     * Dispatch setSelected to all of this View's children.
21140     *
21141     * @see #setSelected(boolean)
21142     *
21143     * @param selected The new selected state
21144     */
21145    protected void dispatchSetSelected(boolean selected) {
21146    }
21147
21148    /**
21149     * Indicates the selection state of this view.
21150     *
21151     * @return true if the view is selected, false otherwise
21152     */
21153    @ViewDebug.ExportedProperty
21154    public boolean isSelected() {
21155        return (mPrivateFlags & PFLAG_SELECTED) != 0;
21156    }
21157
21158    /**
21159     * Changes the activated state of this view. A view can be activated or not.
21160     * Note that activation is not the same as selection.  Selection is
21161     * a transient property, representing the view (hierarchy) the user is
21162     * currently interacting with.  Activation is a longer-term state that the
21163     * user can move views in and out of.  For example, in a list view with
21164     * single or multiple selection enabled, the views in the current selection
21165     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
21166     * here.)  The activated state is propagated down to children of the view it
21167     * is set on.
21168     *
21169     * @param activated true if the view must be activated, false otherwise
21170     */
21171    public void setActivated(boolean activated) {
21172        //noinspection DoubleNegation
21173        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
21174            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
21175            invalidate(true);
21176            refreshDrawableState();
21177            dispatchSetActivated(activated);
21178        }
21179    }
21180
21181    /**
21182     * Dispatch setActivated to all of this View's children.
21183     *
21184     * @see #setActivated(boolean)
21185     *
21186     * @param activated The new activated state
21187     */
21188    protected void dispatchSetActivated(boolean activated) {
21189    }
21190
21191    /**
21192     * Indicates the activation state of this view.
21193     *
21194     * @return true if the view is activated, false otherwise
21195     */
21196    @ViewDebug.ExportedProperty
21197    public boolean isActivated() {
21198        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
21199    }
21200
21201    /**
21202     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
21203     * observer can be used to get notifications when global events, like
21204     * layout, happen.
21205     *
21206     * The returned ViewTreeObserver observer is not guaranteed to remain
21207     * valid for the lifetime of this View. If the caller of this method keeps
21208     * a long-lived reference to ViewTreeObserver, it should always check for
21209     * the return value of {@link ViewTreeObserver#isAlive()}.
21210     *
21211     * @return The ViewTreeObserver for this view's hierarchy.
21212     */
21213    public ViewTreeObserver getViewTreeObserver() {
21214        if (mAttachInfo != null) {
21215            return mAttachInfo.mTreeObserver;
21216        }
21217        if (mFloatingTreeObserver == null) {
21218            mFloatingTreeObserver = new ViewTreeObserver(mContext);
21219        }
21220        return mFloatingTreeObserver;
21221    }
21222
21223    /**
21224     * <p>Finds the topmost view in the current view hierarchy.</p>
21225     *
21226     * @return the topmost view containing this view
21227     */
21228    public View getRootView() {
21229        if (mAttachInfo != null) {
21230            final View v = mAttachInfo.mRootView;
21231            if (v != null) {
21232                return v;
21233            }
21234        }
21235
21236        View parent = this;
21237
21238        while (parent.mParent != null && parent.mParent instanceof View) {
21239            parent = (View) parent.mParent;
21240        }
21241
21242        return parent;
21243    }
21244
21245    /**
21246     * Transforms a motion event from view-local coordinates to on-screen
21247     * coordinates.
21248     *
21249     * @param ev the view-local motion event
21250     * @return false if the transformation could not be applied
21251     * @hide
21252     */
21253    public boolean toGlobalMotionEvent(MotionEvent ev) {
21254        final AttachInfo info = mAttachInfo;
21255        if (info == null) {
21256            return false;
21257        }
21258
21259        final Matrix m = info.mTmpMatrix;
21260        m.set(Matrix.IDENTITY_MATRIX);
21261        transformMatrixToGlobal(m);
21262        ev.transform(m);
21263        return true;
21264    }
21265
21266    /**
21267     * Transforms a motion event from on-screen coordinates to view-local
21268     * coordinates.
21269     *
21270     * @param ev the on-screen motion event
21271     * @return false if the transformation could not be applied
21272     * @hide
21273     */
21274    public boolean toLocalMotionEvent(MotionEvent ev) {
21275        final AttachInfo info = mAttachInfo;
21276        if (info == null) {
21277            return false;
21278        }
21279
21280        final Matrix m = info.mTmpMatrix;
21281        m.set(Matrix.IDENTITY_MATRIX);
21282        transformMatrixToLocal(m);
21283        ev.transform(m);
21284        return true;
21285    }
21286
21287    /**
21288     * Modifies the input matrix such that it maps view-local coordinates to
21289     * on-screen coordinates.
21290     *
21291     * @param m input matrix to modify
21292     * @hide
21293     */
21294    public void transformMatrixToGlobal(Matrix m) {
21295        final ViewParent parent = mParent;
21296        if (parent instanceof View) {
21297            final View vp = (View) parent;
21298            vp.transformMatrixToGlobal(m);
21299            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
21300        } else if (parent instanceof ViewRootImpl) {
21301            final ViewRootImpl vr = (ViewRootImpl) parent;
21302            vr.transformMatrixToGlobal(m);
21303            m.preTranslate(0, -vr.mCurScrollY);
21304        }
21305
21306        m.preTranslate(mLeft, mTop);
21307
21308        if (!hasIdentityMatrix()) {
21309            m.preConcat(getMatrix());
21310        }
21311    }
21312
21313    /**
21314     * Modifies the input matrix such that it maps on-screen coordinates to
21315     * view-local coordinates.
21316     *
21317     * @param m input matrix to modify
21318     * @hide
21319     */
21320    public void transformMatrixToLocal(Matrix m) {
21321        final ViewParent parent = mParent;
21322        if (parent instanceof View) {
21323            final View vp = (View) parent;
21324            vp.transformMatrixToLocal(m);
21325            m.postTranslate(vp.mScrollX, vp.mScrollY);
21326        } else if (parent instanceof ViewRootImpl) {
21327            final ViewRootImpl vr = (ViewRootImpl) parent;
21328            vr.transformMatrixToLocal(m);
21329            m.postTranslate(0, vr.mCurScrollY);
21330        }
21331
21332        m.postTranslate(-mLeft, -mTop);
21333
21334        if (!hasIdentityMatrix()) {
21335            m.postConcat(getInverseMatrix());
21336        }
21337    }
21338
21339    /**
21340     * @hide
21341     */
21342    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
21343            @ViewDebug.IntToString(from = 0, to = "x"),
21344            @ViewDebug.IntToString(from = 1, to = "y")
21345    })
21346    public int[] getLocationOnScreen() {
21347        int[] location = new int[2];
21348        getLocationOnScreen(location);
21349        return location;
21350    }
21351
21352    /**
21353     * <p>Computes the coordinates of this view on the screen. The argument
21354     * must be an array of two integers. After the method returns, the array
21355     * contains the x and y location in that order.</p>
21356     *
21357     * @param outLocation an array of two integers in which to hold the coordinates
21358     */
21359    public void getLocationOnScreen(@Size(2) int[] outLocation) {
21360        getLocationInWindow(outLocation);
21361
21362        final AttachInfo info = mAttachInfo;
21363        if (info != null) {
21364            outLocation[0] += info.mWindowLeft;
21365            outLocation[1] += info.mWindowTop;
21366        }
21367    }
21368
21369    /**
21370     * <p>Computes the coordinates of this view in its window. The argument
21371     * must be an array of two integers. After the method returns, the array
21372     * contains the x and y location in that order.</p>
21373     *
21374     * @param outLocation an array of two integers in which to hold the coordinates
21375     */
21376    public void getLocationInWindow(@Size(2) int[] outLocation) {
21377        if (outLocation == null || outLocation.length < 2) {
21378            throw new IllegalArgumentException("outLocation must be an array of two integers");
21379        }
21380
21381        outLocation[0] = 0;
21382        outLocation[1] = 0;
21383
21384        transformFromViewToWindowSpace(outLocation);
21385    }
21386
21387    /** @hide */
21388    public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
21389        if (inOutLocation == null || inOutLocation.length < 2) {
21390            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
21391        }
21392
21393        if (mAttachInfo == null) {
21394            // When the view is not attached to a window, this method does not make sense
21395            inOutLocation[0] = inOutLocation[1] = 0;
21396            return;
21397        }
21398
21399        float position[] = mAttachInfo.mTmpTransformLocation;
21400        position[0] = inOutLocation[0];
21401        position[1] = inOutLocation[1];
21402
21403        if (!hasIdentityMatrix()) {
21404            getMatrix().mapPoints(position);
21405        }
21406
21407        position[0] += mLeft;
21408        position[1] += mTop;
21409
21410        ViewParent viewParent = mParent;
21411        while (viewParent instanceof View) {
21412            final View view = (View) viewParent;
21413
21414            position[0] -= view.mScrollX;
21415            position[1] -= view.mScrollY;
21416
21417            if (!view.hasIdentityMatrix()) {
21418                view.getMatrix().mapPoints(position);
21419            }
21420
21421            position[0] += view.mLeft;
21422            position[1] += view.mTop;
21423
21424            viewParent = view.mParent;
21425         }
21426
21427        if (viewParent instanceof ViewRootImpl) {
21428            // *cough*
21429            final ViewRootImpl vr = (ViewRootImpl) viewParent;
21430            position[1] -= vr.mCurScrollY;
21431        }
21432
21433        inOutLocation[0] = Math.round(position[0]);
21434        inOutLocation[1] = Math.round(position[1]);
21435    }
21436
21437    /**
21438     * @param id the id of the view to be found
21439     * @return the view of the specified id, null if cannot be found
21440     * @hide
21441     */
21442    protected <T extends View> T findViewTraversal(@IdRes int id) {
21443        if (id == mID) {
21444            return (T) this;
21445        }
21446        return null;
21447    }
21448
21449    /**
21450     * @param tag the tag of the view to be found
21451     * @return the view of specified tag, null if cannot be found
21452     * @hide
21453     */
21454    protected <T extends View> T findViewWithTagTraversal(Object tag) {
21455        if (tag != null && tag.equals(mTag)) {
21456            return (T) this;
21457        }
21458        return null;
21459    }
21460
21461    /**
21462     * @param predicate The predicate to evaluate.
21463     * @param childToSkip If not null, ignores this child during the recursive traversal.
21464     * @return The first view that matches the predicate or null.
21465     * @hide
21466     */
21467    protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
21468            View childToSkip) {
21469        if (predicate.test(this)) {
21470            return (T) this;
21471        }
21472        return null;
21473    }
21474
21475    /**
21476     * Finds the first descendant view with the given ID, the view itself if
21477     * the ID matches {@link #getId()}, or {@code null} if the ID is invalid
21478     * (< 0) or there is no matching view in the hierarchy.
21479     * <p>
21480     * <strong>Note:</strong> In most cases -- depending on compiler support --
21481     * the resulting view is automatically cast to the target class type. If
21482     * the target class type is unconstrained, an explicit cast may be
21483     * necessary.
21484     *
21485     * @param id the ID to search for
21486     * @return a view with given ID if found, or {@code null} otherwise
21487     * @see View#findViewById(int)
21488     */
21489    @Nullable
21490    public final <T extends View> T findViewById(@IdRes int id) {
21491        if (id == NO_ID) {
21492            return null;
21493        }
21494        return findViewTraversal(id);
21495    }
21496
21497    /**
21498     * Finds a view by its unuque and stable accessibility id.
21499     *
21500     * @param accessibilityId The searched accessibility id.
21501     * @return The found view.
21502     */
21503    final <T extends View> T findViewByAccessibilityId(int accessibilityId) {
21504        if (accessibilityId < 0) {
21505            return null;
21506        }
21507        T view = findViewByAccessibilityIdTraversal(accessibilityId);
21508        if (view != null) {
21509            return view.includeForAccessibility() ? view : null;
21510        }
21511        return null;
21512    }
21513
21514    /**
21515     * Performs the traversal to find a view by its unique and stable accessibility id.
21516     *
21517     * <strong>Note:</strong>This method does not stop at the root namespace
21518     * boundary since the user can touch the screen at an arbitrary location
21519     * potentially crossing the root namespace boundary which will send an
21520     * accessibility event to accessibility services and they should be able
21521     * to obtain the event source. Also accessibility ids are guaranteed to be
21522     * unique in the window.
21523     *
21524     * @param accessibilityId The accessibility id.
21525     * @return The found view.
21526     * @hide
21527     */
21528    public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
21529        if (getAccessibilityViewId() == accessibilityId) {
21530            return (T) this;
21531        }
21532        return null;
21533    }
21534
21535    /**
21536     * Performs the traversal to find a view by its autofill id.
21537     *
21538     * <strong>Note:</strong>This method does not stop at the root namespace
21539     * boundary.
21540     *
21541     * @param autofillId The autofill id.
21542     * @return The found view.
21543     * @hide
21544     */
21545    public <T extends View> T findViewByAutofillIdTraversal(int autofillId) {
21546        if (getAutofillViewId() == autofillId) {
21547            return (T) this;
21548        }
21549        return null;
21550    }
21551
21552    /**
21553     * Look for a child view with the given tag.  If this view has the given
21554     * tag, return this view.
21555     *
21556     * @param tag The tag to search for, using "tag.equals(getTag())".
21557     * @return The View that has the given tag in the hierarchy or null
21558     */
21559    public final <T extends View> T findViewWithTag(Object tag) {
21560        if (tag == null) {
21561            return null;
21562        }
21563        return findViewWithTagTraversal(tag);
21564    }
21565
21566    /**
21567     * Look for a child view that matches the specified predicate.
21568     * If this view matches the predicate, return this view.
21569     *
21570     * @param predicate The predicate to evaluate.
21571     * @return The first view that matches the predicate or null.
21572     * @hide
21573     */
21574    public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
21575        return findViewByPredicateTraversal(predicate, null);
21576    }
21577
21578    /**
21579     * Look for a child view that matches the specified predicate,
21580     * starting with the specified view and its descendents and then
21581     * recusively searching the ancestors and siblings of that view
21582     * until this view is reached.
21583     *
21584     * This method is useful in cases where the predicate does not match
21585     * a single unique view (perhaps multiple views use the same id)
21586     * and we are trying to find the view that is "closest" in scope to the
21587     * starting view.
21588     *
21589     * @param start The view to start from.
21590     * @param predicate The predicate to evaluate.
21591     * @return The first view that matches the predicate or null.
21592     * @hide
21593     */
21594    public final <T extends View> T findViewByPredicateInsideOut(
21595            View start, Predicate<View> predicate) {
21596        View childToSkip = null;
21597        for (;;) {
21598            T view = start.findViewByPredicateTraversal(predicate, childToSkip);
21599            if (view != null || start == this) {
21600                return view;
21601            }
21602
21603            ViewParent parent = start.getParent();
21604            if (parent == null || !(parent instanceof View)) {
21605                return null;
21606            }
21607
21608            childToSkip = start;
21609            start = (View) parent;
21610        }
21611    }
21612
21613    /**
21614     * Sets the identifier for this view. The identifier does not have to be
21615     * unique in this view's hierarchy. The identifier should be a positive
21616     * number.
21617     *
21618     * @see #NO_ID
21619     * @see #getId()
21620     * @see #findViewById(int)
21621     *
21622     * @param id a number used to identify the view
21623     *
21624     * @attr ref android.R.styleable#View_id
21625     */
21626    public void setId(@IdRes int id) {
21627        mID = id;
21628        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
21629            mID = generateViewId();
21630        }
21631    }
21632
21633    /**
21634     * {@hide}
21635     *
21636     * @param isRoot true if the view belongs to the root namespace, false
21637     *        otherwise
21638     */
21639    public void setIsRootNamespace(boolean isRoot) {
21640        if (isRoot) {
21641            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
21642        } else {
21643            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
21644        }
21645    }
21646
21647    /**
21648     * {@hide}
21649     *
21650     * @return true if the view belongs to the root namespace, false otherwise
21651     */
21652    public boolean isRootNamespace() {
21653        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
21654    }
21655
21656    /**
21657     * Returns this view's identifier.
21658     *
21659     * @return a positive integer used to identify the view or {@link #NO_ID}
21660     *         if the view has no ID
21661     *
21662     * @see #setId(int)
21663     * @see #findViewById(int)
21664     * @attr ref android.R.styleable#View_id
21665     */
21666    @IdRes
21667    @ViewDebug.CapturedViewProperty
21668    public int getId() {
21669        return mID;
21670    }
21671
21672    /**
21673     * Returns this view's tag.
21674     *
21675     * @return the Object stored in this view as a tag, or {@code null} if not
21676     *         set
21677     *
21678     * @see #setTag(Object)
21679     * @see #getTag(int)
21680     */
21681    @ViewDebug.ExportedProperty
21682    public Object getTag() {
21683        return mTag;
21684    }
21685
21686    /**
21687     * Sets the tag associated with this view. A tag can be used to mark
21688     * a view in its hierarchy and does not have to be unique within the
21689     * hierarchy. Tags can also be used to store data within a view without
21690     * resorting to another data structure.
21691     *
21692     * @param tag an Object to tag the view with
21693     *
21694     * @see #getTag()
21695     * @see #setTag(int, Object)
21696     */
21697    public void setTag(final Object tag) {
21698        mTag = tag;
21699    }
21700
21701    /**
21702     * Returns the tag associated with this view and the specified key.
21703     *
21704     * @param key The key identifying the tag
21705     *
21706     * @return the Object stored in this view as a tag, or {@code null} if not
21707     *         set
21708     *
21709     * @see #setTag(int, Object)
21710     * @see #getTag()
21711     */
21712    public Object getTag(int key) {
21713        if (mKeyedTags != null) return mKeyedTags.get(key);
21714        return null;
21715    }
21716
21717    /**
21718     * Sets a tag associated with this view and a key. A tag can be used
21719     * to mark a view in its hierarchy and does not have to be unique within
21720     * the hierarchy. Tags can also be used to store data within a view
21721     * without resorting to another data structure.
21722     *
21723     * The specified key should be an id declared in the resources of the
21724     * application to ensure it is unique (see the <a
21725     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
21726     * Keys identified as belonging to
21727     * the Android framework or not associated with any package will cause
21728     * an {@link IllegalArgumentException} to be thrown.
21729     *
21730     * @param key The key identifying the tag
21731     * @param tag An Object to tag the view with
21732     *
21733     * @throws IllegalArgumentException If they specified key is not valid
21734     *
21735     * @see #setTag(Object)
21736     * @see #getTag(int)
21737     */
21738    public void setTag(int key, final Object tag) {
21739        // If the package id is 0x00 or 0x01, it's either an undefined package
21740        // or a framework id
21741        if ((key >>> 24) < 2) {
21742            throw new IllegalArgumentException("The key must be an application-specific "
21743                    + "resource id.");
21744        }
21745
21746        setKeyedTag(key, tag);
21747    }
21748
21749    /**
21750     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
21751     * framework id.
21752     *
21753     * @hide
21754     */
21755    public void setTagInternal(int key, Object tag) {
21756        if ((key >>> 24) != 0x1) {
21757            throw new IllegalArgumentException("The key must be a framework-specific "
21758                    + "resource id.");
21759        }
21760
21761        setKeyedTag(key, tag);
21762    }
21763
21764    private void setKeyedTag(int key, Object tag) {
21765        if (mKeyedTags == null) {
21766            mKeyedTags = new SparseArray<Object>(2);
21767        }
21768
21769        mKeyedTags.put(key, tag);
21770    }
21771
21772    /**
21773     * Prints information about this view in the log output, with the tag
21774     * {@link #VIEW_LOG_TAG}.
21775     *
21776     * @hide
21777     */
21778    public void debug() {
21779        debug(0);
21780    }
21781
21782    /**
21783     * Prints information about this view in the log output, with the tag
21784     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
21785     * indentation defined by the <code>depth</code>.
21786     *
21787     * @param depth the indentation level
21788     *
21789     * @hide
21790     */
21791    protected void debug(int depth) {
21792        String output = debugIndent(depth - 1);
21793
21794        output += "+ " + this;
21795        int id = getId();
21796        if (id != -1) {
21797            output += " (id=" + id + ")";
21798        }
21799        Object tag = getTag();
21800        if (tag != null) {
21801            output += " (tag=" + tag + ")";
21802        }
21803        Log.d(VIEW_LOG_TAG, output);
21804
21805        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
21806            output = debugIndent(depth) + " FOCUSED";
21807            Log.d(VIEW_LOG_TAG, output);
21808        }
21809
21810        output = debugIndent(depth);
21811        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
21812                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
21813                + "} ";
21814        Log.d(VIEW_LOG_TAG, output);
21815
21816        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
21817                || mPaddingBottom != 0) {
21818            output = debugIndent(depth);
21819            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
21820                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
21821            Log.d(VIEW_LOG_TAG, output);
21822        }
21823
21824        output = debugIndent(depth);
21825        output += "mMeasureWidth=" + mMeasuredWidth +
21826                " mMeasureHeight=" + mMeasuredHeight;
21827        Log.d(VIEW_LOG_TAG, output);
21828
21829        output = debugIndent(depth);
21830        if (mLayoutParams == null) {
21831            output += "BAD! no layout params";
21832        } else {
21833            output = mLayoutParams.debug(output);
21834        }
21835        Log.d(VIEW_LOG_TAG, output);
21836
21837        output = debugIndent(depth);
21838        output += "flags={";
21839        output += View.printFlags(mViewFlags);
21840        output += "}";
21841        Log.d(VIEW_LOG_TAG, output);
21842
21843        output = debugIndent(depth);
21844        output += "privateFlags={";
21845        output += View.printPrivateFlags(mPrivateFlags);
21846        output += "}";
21847        Log.d(VIEW_LOG_TAG, output);
21848    }
21849
21850    /**
21851     * Creates a string of whitespaces used for indentation.
21852     *
21853     * @param depth the indentation level
21854     * @return a String containing (depth * 2 + 3) * 2 white spaces
21855     *
21856     * @hide
21857     */
21858    protected static String debugIndent(int depth) {
21859        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
21860        for (int i = 0; i < (depth * 2) + 3; i++) {
21861            spaces.append(' ').append(' ');
21862        }
21863        return spaces.toString();
21864    }
21865
21866    /**
21867     * <p>Return the offset of the widget's text baseline from the widget's top
21868     * boundary. If this widget does not support baseline alignment, this
21869     * method returns -1. </p>
21870     *
21871     * @return the offset of the baseline within the widget's bounds or -1
21872     *         if baseline alignment is not supported
21873     */
21874    @ViewDebug.ExportedProperty(category = "layout")
21875    public int getBaseline() {
21876        return -1;
21877    }
21878
21879    /**
21880     * Returns whether the view hierarchy is currently undergoing a layout pass. This
21881     * information is useful to avoid situations such as calling {@link #requestLayout()} during
21882     * a layout pass.
21883     *
21884     * @return whether the view hierarchy is currently undergoing a layout pass
21885     */
21886    public boolean isInLayout() {
21887        ViewRootImpl viewRoot = getViewRootImpl();
21888        return (viewRoot != null && viewRoot.isInLayout());
21889    }
21890
21891    /**
21892     * Call this when something has changed which has invalidated the
21893     * layout of this view. This will schedule a layout pass of the view
21894     * tree. This should not be called while the view hierarchy is currently in a layout
21895     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
21896     * end of the current layout pass (and then layout will run again) or after the current
21897     * frame is drawn and the next layout occurs.
21898     *
21899     * <p>Subclasses which override this method should call the superclass method to
21900     * handle possible request-during-layout errors correctly.</p>
21901     */
21902    @CallSuper
21903    public void requestLayout() {
21904        if (mMeasureCache != null) mMeasureCache.clear();
21905
21906        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
21907            // Only trigger request-during-layout logic if this is the view requesting it,
21908            // not the views in its parent hierarchy
21909            ViewRootImpl viewRoot = getViewRootImpl();
21910            if (viewRoot != null && viewRoot.isInLayout()) {
21911                if (!viewRoot.requestLayoutDuringLayout(this)) {
21912                    return;
21913                }
21914            }
21915            mAttachInfo.mViewRequestingLayout = this;
21916        }
21917
21918        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21919        mPrivateFlags |= PFLAG_INVALIDATED;
21920
21921        if (mParent != null && !mParent.isLayoutRequested()) {
21922            mParent.requestLayout();
21923        }
21924        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
21925            mAttachInfo.mViewRequestingLayout = null;
21926        }
21927    }
21928
21929    /**
21930     * Forces this view to be laid out during the next layout pass.
21931     * This method does not call requestLayout() or forceLayout()
21932     * on the parent.
21933     */
21934    public void forceLayout() {
21935        if (mMeasureCache != null) mMeasureCache.clear();
21936
21937        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
21938        mPrivateFlags |= PFLAG_INVALIDATED;
21939    }
21940
21941    /**
21942     * <p>
21943     * This is called to find out how big a view should be. The parent
21944     * supplies constraint information in the width and height parameters.
21945     * </p>
21946     *
21947     * <p>
21948     * The actual measurement work of a view is performed in
21949     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
21950     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
21951     * </p>
21952     *
21953     *
21954     * @param widthMeasureSpec Horizontal space requirements as imposed by the
21955     *        parent
21956     * @param heightMeasureSpec Vertical space requirements as imposed by the
21957     *        parent
21958     *
21959     * @see #onMeasure(int, int)
21960     */
21961    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
21962        boolean optical = isLayoutModeOptical(this);
21963        if (optical != isLayoutModeOptical(mParent)) {
21964            Insets insets = getOpticalInsets();
21965            int oWidth  = insets.left + insets.right;
21966            int oHeight = insets.top  + insets.bottom;
21967            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
21968            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
21969        }
21970
21971        // Suppress sign extension for the low bytes
21972        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
21973        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
21974
21975        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
21976
21977        // Optimize layout by avoiding an extra EXACTLY pass when the view is
21978        // already measured as the correct size. In API 23 and below, this
21979        // extra pass is required to make LinearLayout re-distribute weight.
21980        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
21981                || heightMeasureSpec != mOldHeightMeasureSpec;
21982        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
21983                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
21984        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
21985                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
21986        final boolean needsLayout = specChanged
21987                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
21988
21989        if (forceLayout || needsLayout) {
21990            // first clears the measured dimension flag
21991            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
21992
21993            resolveRtlPropertiesIfNeeded();
21994
21995            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
21996            if (cacheIndex < 0 || sIgnoreMeasureCache) {
21997                // measure ourselves, this should set the measured dimension flag back
21998                onMeasure(widthMeasureSpec, heightMeasureSpec);
21999                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
22000            } else {
22001                long value = mMeasureCache.valueAt(cacheIndex);
22002                // Casting a long to int drops the high 32 bits, no mask needed
22003                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
22004                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
22005            }
22006
22007            // flag not set, setMeasuredDimension() was not invoked, we raise
22008            // an exception to warn the developer
22009            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
22010                throw new IllegalStateException("View with id " + getId() + ": "
22011                        + getClass().getName() + "#onMeasure() did not set the"
22012                        + " measured dimension by calling"
22013                        + " setMeasuredDimension()");
22014            }
22015
22016            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
22017        }
22018
22019        mOldWidthMeasureSpec = widthMeasureSpec;
22020        mOldHeightMeasureSpec = heightMeasureSpec;
22021
22022        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
22023                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
22024    }
22025
22026    /**
22027     * <p>
22028     * Measure the view and its content to determine the measured width and the
22029     * measured height. This method is invoked by {@link #measure(int, int)} and
22030     * should be overridden by subclasses to provide accurate and efficient
22031     * measurement of their contents.
22032     * </p>
22033     *
22034     * <p>
22035     * <strong>CONTRACT:</strong> When overriding this method, you
22036     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
22037     * measured width and height of this view. Failure to do so will trigger an
22038     * <code>IllegalStateException</code>, thrown by
22039     * {@link #measure(int, int)}. Calling the superclass'
22040     * {@link #onMeasure(int, int)} is a valid use.
22041     * </p>
22042     *
22043     * <p>
22044     * The base class implementation of measure defaults to the background size,
22045     * unless a larger size is allowed by the MeasureSpec. Subclasses should
22046     * override {@link #onMeasure(int, int)} to provide better measurements of
22047     * their content.
22048     * </p>
22049     *
22050     * <p>
22051     * If this method is overridden, it is the subclass's responsibility to make
22052     * sure the measured height and width are at least the view's minimum height
22053     * and width ({@link #getSuggestedMinimumHeight()} and
22054     * {@link #getSuggestedMinimumWidth()}).
22055     * </p>
22056     *
22057     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
22058     *                         The requirements are encoded with
22059     *                         {@link android.view.View.MeasureSpec}.
22060     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
22061     *                         The requirements are encoded with
22062     *                         {@link android.view.View.MeasureSpec}.
22063     *
22064     * @see #getMeasuredWidth()
22065     * @see #getMeasuredHeight()
22066     * @see #setMeasuredDimension(int, int)
22067     * @see #getSuggestedMinimumHeight()
22068     * @see #getSuggestedMinimumWidth()
22069     * @see android.view.View.MeasureSpec#getMode(int)
22070     * @see android.view.View.MeasureSpec#getSize(int)
22071     */
22072    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
22073        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
22074                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
22075    }
22076
22077    /**
22078     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
22079     * measured width and measured height. Failing to do so will trigger an
22080     * exception at measurement time.</p>
22081     *
22082     * @param measuredWidth The measured width of this view.  May be a complex
22083     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22084     * {@link #MEASURED_STATE_TOO_SMALL}.
22085     * @param measuredHeight The measured height of this view.  May be a complex
22086     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22087     * {@link #MEASURED_STATE_TOO_SMALL}.
22088     */
22089    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
22090        boolean optical = isLayoutModeOptical(this);
22091        if (optical != isLayoutModeOptical(mParent)) {
22092            Insets insets = getOpticalInsets();
22093            int opticalWidth  = insets.left + insets.right;
22094            int opticalHeight = insets.top  + insets.bottom;
22095
22096            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
22097            measuredHeight += optical ? opticalHeight : -opticalHeight;
22098        }
22099        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
22100    }
22101
22102    /**
22103     * Sets the measured dimension without extra processing for things like optical bounds.
22104     * Useful for reapplying consistent values that have already been cooked with adjustments
22105     * for optical bounds, etc. such as those from the measurement cache.
22106     *
22107     * @param measuredWidth The measured width of this view.  May be a complex
22108     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22109     * {@link #MEASURED_STATE_TOO_SMALL}.
22110     * @param measuredHeight The measured height of this view.  May be a complex
22111     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
22112     * {@link #MEASURED_STATE_TOO_SMALL}.
22113     */
22114    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
22115        mMeasuredWidth = measuredWidth;
22116        mMeasuredHeight = measuredHeight;
22117
22118        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
22119    }
22120
22121    /**
22122     * Merge two states as returned by {@link #getMeasuredState()}.
22123     * @param curState The current state as returned from a view or the result
22124     * of combining multiple views.
22125     * @param newState The new view state to combine.
22126     * @return Returns a new integer reflecting the combination of the two
22127     * states.
22128     */
22129    public static int combineMeasuredStates(int curState, int newState) {
22130        return curState | newState;
22131    }
22132
22133    /**
22134     * Version of {@link #resolveSizeAndState(int, int, int)}
22135     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
22136     */
22137    public static int resolveSize(int size, int measureSpec) {
22138        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
22139    }
22140
22141    /**
22142     * Utility to reconcile a desired size and state, with constraints imposed
22143     * by a MeasureSpec. Will take the desired size, unless a different size
22144     * is imposed by the constraints. The returned value is a compound integer,
22145     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
22146     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
22147     * resulting size is smaller than the size the view wants to be.
22148     *
22149     * @param size How big the view wants to be.
22150     * @param measureSpec Constraints imposed by the parent.
22151     * @param childMeasuredState Size information bit mask for the view's
22152     *                           children.
22153     * @return Size information bit mask as defined by
22154     *         {@link #MEASURED_SIZE_MASK} and
22155     *         {@link #MEASURED_STATE_TOO_SMALL}.
22156     */
22157    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
22158        final int specMode = MeasureSpec.getMode(measureSpec);
22159        final int specSize = MeasureSpec.getSize(measureSpec);
22160        final int result;
22161        switch (specMode) {
22162            case MeasureSpec.AT_MOST:
22163                if (specSize < size) {
22164                    result = specSize | MEASURED_STATE_TOO_SMALL;
22165                } else {
22166                    result = size;
22167                }
22168                break;
22169            case MeasureSpec.EXACTLY:
22170                result = specSize;
22171                break;
22172            case MeasureSpec.UNSPECIFIED:
22173            default:
22174                result = size;
22175        }
22176        return result | (childMeasuredState & MEASURED_STATE_MASK);
22177    }
22178
22179    /**
22180     * Utility to return a default size. Uses the supplied size if the
22181     * MeasureSpec imposed no constraints. Will get larger if allowed
22182     * by the MeasureSpec.
22183     *
22184     * @param size Default size for this view
22185     * @param measureSpec Constraints imposed by the parent
22186     * @return The size this view should be.
22187     */
22188    public static int getDefaultSize(int size, int measureSpec) {
22189        int result = size;
22190        int specMode = MeasureSpec.getMode(measureSpec);
22191        int specSize = MeasureSpec.getSize(measureSpec);
22192
22193        switch (specMode) {
22194        case MeasureSpec.UNSPECIFIED:
22195            result = size;
22196            break;
22197        case MeasureSpec.AT_MOST:
22198        case MeasureSpec.EXACTLY:
22199            result = specSize;
22200            break;
22201        }
22202        return result;
22203    }
22204
22205    /**
22206     * Returns the suggested minimum height that the view should use. This
22207     * returns the maximum of the view's minimum height
22208     * and the background's minimum height
22209     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
22210     * <p>
22211     * When being used in {@link #onMeasure(int, int)}, the caller should still
22212     * ensure the returned height is within the requirements of the parent.
22213     *
22214     * @return The suggested minimum height of the view.
22215     */
22216    protected int getSuggestedMinimumHeight() {
22217        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
22218
22219    }
22220
22221    /**
22222     * Returns the suggested minimum width that the view should use. This
22223     * returns the maximum of the view's minimum width
22224     * and the background's minimum width
22225     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
22226     * <p>
22227     * When being used in {@link #onMeasure(int, int)}, the caller should still
22228     * ensure the returned width is within the requirements of the parent.
22229     *
22230     * @return The suggested minimum width of the view.
22231     */
22232    protected int getSuggestedMinimumWidth() {
22233        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
22234    }
22235
22236    /**
22237     * Returns the minimum height of the view.
22238     *
22239     * @return the minimum height the view will try to be, in pixels
22240     *
22241     * @see #setMinimumHeight(int)
22242     *
22243     * @attr ref android.R.styleable#View_minHeight
22244     */
22245    public int getMinimumHeight() {
22246        return mMinHeight;
22247    }
22248
22249    /**
22250     * Sets the minimum height of the view. It is not guaranteed the view will
22251     * be able to achieve this minimum height (for example, if its parent layout
22252     * constrains it with less available height).
22253     *
22254     * @param minHeight The minimum height the view will try to be, in pixels
22255     *
22256     * @see #getMinimumHeight()
22257     *
22258     * @attr ref android.R.styleable#View_minHeight
22259     */
22260    @RemotableViewMethod
22261    public void setMinimumHeight(int minHeight) {
22262        mMinHeight = minHeight;
22263        requestLayout();
22264    }
22265
22266    /**
22267     * Returns the minimum width of the view.
22268     *
22269     * @return the minimum width the view will try to be, in pixels
22270     *
22271     * @see #setMinimumWidth(int)
22272     *
22273     * @attr ref android.R.styleable#View_minWidth
22274     */
22275    public int getMinimumWidth() {
22276        return mMinWidth;
22277    }
22278
22279    /**
22280     * Sets the minimum width of the view. It is not guaranteed the view will
22281     * be able to achieve this minimum width (for example, if its parent layout
22282     * constrains it with less available width).
22283     *
22284     * @param minWidth The minimum width the view will try to be, in pixels
22285     *
22286     * @see #getMinimumWidth()
22287     *
22288     * @attr ref android.R.styleable#View_minWidth
22289     */
22290    public void setMinimumWidth(int minWidth) {
22291        mMinWidth = minWidth;
22292        requestLayout();
22293
22294    }
22295
22296    /**
22297     * Get the animation currently associated with this view.
22298     *
22299     * @return The animation that is currently playing or
22300     *         scheduled to play for this view.
22301     */
22302    public Animation getAnimation() {
22303        return mCurrentAnimation;
22304    }
22305
22306    /**
22307     * Start the specified animation now.
22308     *
22309     * @param animation the animation to start now
22310     */
22311    public void startAnimation(Animation animation) {
22312        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
22313        setAnimation(animation);
22314        invalidateParentCaches();
22315        invalidate(true);
22316    }
22317
22318    /**
22319     * Cancels any animations for this view.
22320     */
22321    public void clearAnimation() {
22322        if (mCurrentAnimation != null) {
22323            mCurrentAnimation.detach();
22324        }
22325        mCurrentAnimation = null;
22326        invalidateParentIfNeeded();
22327    }
22328
22329    /**
22330     * Sets the next animation to play for this view.
22331     * If you want the animation to play immediately, use
22332     * {@link #startAnimation(android.view.animation.Animation)} instead.
22333     * This method provides allows fine-grained
22334     * control over the start time and invalidation, but you
22335     * must make sure that 1) the animation has a start time set, and
22336     * 2) the view's parent (which controls animations on its children)
22337     * will be invalidated when the animation is supposed to
22338     * start.
22339     *
22340     * @param animation The next animation, or null.
22341     */
22342    public void setAnimation(Animation animation) {
22343        mCurrentAnimation = animation;
22344
22345        if (animation != null) {
22346            // If the screen is off assume the animation start time is now instead of
22347            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
22348            // would cause the animation to start when the screen turns back on
22349            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
22350                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
22351                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
22352            }
22353            animation.reset();
22354        }
22355    }
22356
22357    /**
22358     * Invoked by a parent ViewGroup to notify the start of the animation
22359     * currently associated with this view. If you override this method,
22360     * always call super.onAnimationStart();
22361     *
22362     * @see #setAnimation(android.view.animation.Animation)
22363     * @see #getAnimation()
22364     */
22365    @CallSuper
22366    protected void onAnimationStart() {
22367        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
22368    }
22369
22370    /**
22371     * Invoked by a parent ViewGroup to notify the end of the animation
22372     * currently associated with this view. If you override this method,
22373     * always call super.onAnimationEnd();
22374     *
22375     * @see #setAnimation(android.view.animation.Animation)
22376     * @see #getAnimation()
22377     */
22378    @CallSuper
22379    protected void onAnimationEnd() {
22380        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
22381    }
22382
22383    /**
22384     * Invoked if there is a Transform that involves alpha. Subclass that can
22385     * draw themselves with the specified alpha should return true, and then
22386     * respect that alpha when their onDraw() is called. If this returns false
22387     * then the view may be redirected to draw into an offscreen buffer to
22388     * fulfill the request, which will look fine, but may be slower than if the
22389     * subclass handles it internally. The default implementation returns false.
22390     *
22391     * @param alpha The alpha (0..255) to apply to the view's drawing
22392     * @return true if the view can draw with the specified alpha.
22393     */
22394    protected boolean onSetAlpha(int alpha) {
22395        return false;
22396    }
22397
22398    /**
22399     * This is used by the RootView to perform an optimization when
22400     * the view hierarchy contains one or several SurfaceView.
22401     * SurfaceView is always considered transparent, but its children are not,
22402     * therefore all View objects remove themselves from the global transparent
22403     * region (passed as a parameter to this function).
22404     *
22405     * @param region The transparent region for this ViewAncestor (window).
22406     *
22407     * @return Returns true if the effective visibility of the view at this
22408     * point is opaque, regardless of the transparent region; returns false
22409     * if it is possible for underlying windows to be seen behind the view.
22410     *
22411     * {@hide}
22412     */
22413    public boolean gatherTransparentRegion(Region region) {
22414        final AttachInfo attachInfo = mAttachInfo;
22415        if (region != null && attachInfo != null) {
22416            final int pflags = mPrivateFlags;
22417            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
22418                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
22419                // remove it from the transparent region.
22420                final int[] location = attachInfo.mTransparentLocation;
22421                getLocationInWindow(location);
22422                // When a view has Z value, then it will be better to leave some area below the view
22423                // for drawing shadow. The shadow outset is proportional to the Z value. Note that
22424                // the bottom part needs more offset than the left, top and right parts due to the
22425                // spot light effects.
22426                int shadowOffset = getZ() > 0 ? (int) getZ() : 0;
22427                region.op(location[0] - shadowOffset, location[1] - shadowOffset,
22428                        location[0] + mRight - mLeft + shadowOffset,
22429                        location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE);
22430            } else {
22431                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
22432                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
22433                    // the background drawable's non-transparent parts from this transparent region.
22434                    applyDrawableToTransparentRegion(mBackground, region);
22435                }
22436                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
22437                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
22438                    // Similarly, we remove the foreground drawable's non-transparent parts.
22439                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
22440                }
22441                if (mDefaultFocusHighlight != null
22442                        && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) {
22443                    // Similarly, we remove the default focus highlight's non-transparent parts.
22444                    applyDrawableToTransparentRegion(mDefaultFocusHighlight, region);
22445                }
22446            }
22447        }
22448        return true;
22449    }
22450
22451    /**
22452     * Play a sound effect for this view.
22453     *
22454     * <p>The framework will play sound effects for some built in actions, such as
22455     * clicking, but you may wish to play these effects in your widget,
22456     * for instance, for internal navigation.
22457     *
22458     * <p>The sound effect will only be played if sound effects are enabled by the user, and
22459     * {@link #isSoundEffectsEnabled()} is true.
22460     *
22461     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
22462     */
22463    public void playSoundEffect(int soundConstant) {
22464        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
22465            return;
22466        }
22467        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
22468    }
22469
22470    /**
22471     * BZZZTT!!1!
22472     *
22473     * <p>Provide haptic feedback to the user for this view.
22474     *
22475     * <p>The framework will provide haptic feedback for some built in actions,
22476     * such as long presses, but you may wish to provide feedback for your
22477     * own widget.
22478     *
22479     * <p>The feedback will only be performed if
22480     * {@link #isHapticFeedbackEnabled()} is true.
22481     *
22482     * @param feedbackConstant One of the constants defined in
22483     * {@link HapticFeedbackConstants}
22484     */
22485    public boolean performHapticFeedback(int feedbackConstant) {
22486        return performHapticFeedback(feedbackConstant, 0);
22487    }
22488
22489    /**
22490     * BZZZTT!!1!
22491     *
22492     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
22493     *
22494     * @param feedbackConstant One of the constants defined in
22495     * {@link HapticFeedbackConstants}
22496     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
22497     */
22498    public boolean performHapticFeedback(int feedbackConstant, int flags) {
22499        if (mAttachInfo == null) {
22500            return false;
22501        }
22502        //noinspection SimplifiableIfStatement
22503        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
22504                && !isHapticFeedbackEnabled()) {
22505            return false;
22506        }
22507        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
22508                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
22509    }
22510
22511    /**
22512     * Request that the visibility of the status bar or other screen/window
22513     * decorations be changed.
22514     *
22515     * <p>This method is used to put the over device UI into temporary modes
22516     * where the user's attention is focused more on the application content,
22517     * by dimming or hiding surrounding system affordances.  This is typically
22518     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
22519     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
22520     * to be placed behind the action bar (and with these flags other system
22521     * affordances) so that smooth transitions between hiding and showing them
22522     * can be done.
22523     *
22524     * <p>Two representative examples of the use of system UI visibility is
22525     * implementing a content browsing application (like a magazine reader)
22526     * and a video playing application.
22527     *
22528     * <p>The first code shows a typical implementation of a View in a content
22529     * browsing application.  In this implementation, the application goes
22530     * into a content-oriented mode by hiding the status bar and action bar,
22531     * and putting the navigation elements into lights out mode.  The user can
22532     * then interact with content while in this mode.  Such an application should
22533     * provide an easy way for the user to toggle out of the mode (such as to
22534     * check information in the status bar or access notifications).  In the
22535     * implementation here, this is done simply by tapping on the content.
22536     *
22537     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
22538     *      content}
22539     *
22540     * <p>This second code sample shows a typical implementation of a View
22541     * in a video playing application.  In this situation, while the video is
22542     * playing the application would like to go into a complete full-screen mode,
22543     * to use as much of the display as possible for the video.  When in this state
22544     * the user can not interact with the application; the system intercepts
22545     * touching on the screen to pop the UI out of full screen mode.  See
22546     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
22547     *
22548     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
22549     *      content}
22550     *
22551     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22552     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22553     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22554     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22555     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22556     */
22557    public void setSystemUiVisibility(int visibility) {
22558        if (visibility != mSystemUiVisibility) {
22559            mSystemUiVisibility = visibility;
22560            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22561                mParent.recomputeViewAttributes(this);
22562            }
22563        }
22564    }
22565
22566    /**
22567     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
22568     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
22569     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
22570     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
22571     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
22572     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
22573     */
22574    public int getSystemUiVisibility() {
22575        return mSystemUiVisibility;
22576    }
22577
22578    /**
22579     * Returns the current system UI visibility that is currently set for
22580     * the entire window.  This is the combination of the
22581     * {@link #setSystemUiVisibility(int)} values supplied by all of the
22582     * views in the window.
22583     */
22584    public int getWindowSystemUiVisibility() {
22585        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
22586    }
22587
22588    /**
22589     * Override to find out when the window's requested system UI visibility
22590     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
22591     * This is different from the callbacks received through
22592     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
22593     * in that this is only telling you about the local request of the window,
22594     * not the actual values applied by the system.
22595     */
22596    public void onWindowSystemUiVisibilityChanged(int visible) {
22597    }
22598
22599    /**
22600     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
22601     * the view hierarchy.
22602     */
22603    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
22604        onWindowSystemUiVisibilityChanged(visible);
22605    }
22606
22607    /**
22608     * Set a listener to receive callbacks when the visibility of the system bar changes.
22609     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
22610     */
22611    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
22612        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
22613        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
22614            mParent.recomputeViewAttributes(this);
22615        }
22616    }
22617
22618    /**
22619     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
22620     * the view hierarchy.
22621     */
22622    public void dispatchSystemUiVisibilityChanged(int visibility) {
22623        ListenerInfo li = mListenerInfo;
22624        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
22625            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
22626                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
22627        }
22628    }
22629
22630    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
22631        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
22632        if (val != mSystemUiVisibility) {
22633            setSystemUiVisibility(val);
22634            return true;
22635        }
22636        return false;
22637    }
22638
22639    /** @hide */
22640    public void setDisabledSystemUiVisibility(int flags) {
22641        if (mAttachInfo != null) {
22642            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
22643                mAttachInfo.mDisabledSystemUiVisibility = flags;
22644                if (mParent != null) {
22645                    mParent.recomputeViewAttributes(this);
22646                }
22647            }
22648        }
22649    }
22650
22651    /**
22652     * Creates an image that the system displays during the drag and drop
22653     * operation. This is called a &quot;drag shadow&quot;. The default implementation
22654     * for a DragShadowBuilder based on a View returns an image that has exactly the same
22655     * appearance as the given View. The default also positions the center of the drag shadow
22656     * directly under the touch point. If no View is provided (the constructor with no parameters
22657     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
22658     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
22659     * default is an invisible drag shadow.
22660     * <p>
22661     * You are not required to use the View you provide to the constructor as the basis of the
22662     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
22663     * anything you want as the drag shadow.
22664     * </p>
22665     * <p>
22666     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
22667     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
22668     *  size and position of the drag shadow. It uses this data to construct a
22669     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
22670     *  so that your application can draw the shadow image in the Canvas.
22671     * </p>
22672     *
22673     * <div class="special reference">
22674     * <h3>Developer Guides</h3>
22675     * <p>For a guide to implementing drag and drop features, read the
22676     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
22677     * </div>
22678     */
22679    public static class DragShadowBuilder {
22680        private final WeakReference<View> mView;
22681
22682        /**
22683         * Constructs a shadow image builder based on a View. By default, the resulting drag
22684         * shadow will have the same appearance and dimensions as the View, with the touch point
22685         * over the center of the View.
22686         * @param view A View. Any View in scope can be used.
22687         */
22688        public DragShadowBuilder(View view) {
22689            mView = new WeakReference<View>(view);
22690        }
22691
22692        /**
22693         * Construct a shadow builder object with no associated View.  This
22694         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
22695         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
22696         * to supply the drag shadow's dimensions and appearance without
22697         * reference to any View object. If they are not overridden, then the result is an
22698         * invisible drag shadow.
22699         */
22700        public DragShadowBuilder() {
22701            mView = new WeakReference<View>(null);
22702        }
22703
22704        /**
22705         * Returns the View object that had been passed to the
22706         * {@link #View.DragShadowBuilder(View)}
22707         * constructor.  If that View parameter was {@code null} or if the
22708         * {@link #View.DragShadowBuilder()}
22709         * constructor was used to instantiate the builder object, this method will return
22710         * null.
22711         *
22712         * @return The View object associate with this builder object.
22713         */
22714        @SuppressWarnings({"JavadocReference"})
22715        final public View getView() {
22716            return mView.get();
22717        }
22718
22719        /**
22720         * Provides the metrics for the shadow image. These include the dimensions of
22721         * the shadow image, and the point within that shadow that should
22722         * be centered under the touch location while dragging.
22723         * <p>
22724         * The default implementation sets the dimensions of the shadow to be the
22725         * same as the dimensions of the View itself and centers the shadow under
22726         * the touch point.
22727         * </p>
22728         *
22729         * @param outShadowSize A {@link android.graphics.Point} containing the width and height
22730         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
22731         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
22732         * image.
22733         *
22734         * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
22735         * shadow image that should be underneath the touch point during the drag and drop
22736         * operation. Your application must set {@link android.graphics.Point#x} to the
22737         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
22738         */
22739        public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
22740            final View view = mView.get();
22741            if (view != null) {
22742                outShadowSize.set(view.getWidth(), view.getHeight());
22743                outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2);
22744            } else {
22745                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
22746            }
22747        }
22748
22749        /**
22750         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
22751         * based on the dimensions it received from the
22752         * {@link #onProvideShadowMetrics(Point, Point)} callback.
22753         *
22754         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
22755         */
22756        public void onDrawShadow(Canvas canvas) {
22757            final View view = mView.get();
22758            if (view != null) {
22759                view.draw(canvas);
22760            } else {
22761                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
22762            }
22763        }
22764    }
22765
22766    /**
22767     * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)
22768     * startDragAndDrop()} for newer platform versions.
22769     */
22770    @Deprecated
22771    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
22772                                   Object myLocalState, int flags) {
22773        return startDragAndDrop(data, shadowBuilder, myLocalState, flags);
22774    }
22775
22776    /**
22777     * Starts a drag and drop operation. When your application calls this method, it passes a
22778     * {@link android.view.View.DragShadowBuilder} object to the system. The
22779     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
22780     * to get metrics for the drag shadow, and then calls the object's
22781     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
22782     * <p>
22783     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
22784     *  drag events to all the View objects in your application that are currently visible. It does
22785     *  this either by calling the View object's drag listener (an implementation of
22786     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
22787     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
22788     *  Both are passed a {@link android.view.DragEvent} object that has a
22789     *  {@link android.view.DragEvent#getAction()} value of
22790     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
22791     * </p>
22792     * <p>
22793     * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object,
22794     * int) startDragAndDrop()} on any attached View object. The View object does not need to be
22795     * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related
22796     * to the View the user selected for dragging.
22797     * </p>
22798     * @param data A {@link android.content.ClipData} object pointing to the data to be
22799     * transferred by the drag and drop operation.
22800     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22801     * drag shadow.
22802     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
22803     * drop operation. When dispatching drag events to views in the same activity this object
22804     * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other
22805     * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()}
22806     * will return null).
22807     * <p>
22808     * myLocalState is a lightweight mechanism for the sending information from the dragged View
22809     * to the target Views. For example, it can contain flags that differentiate between a
22810     * a copy operation and a move operation.
22811     * </p>
22812     * @param flags Flags that control the drag and drop operation. This can be set to 0 for no
22813     * flags, or any combination of the following:
22814     *     <ul>
22815     *         <li>{@link #DRAG_FLAG_GLOBAL}</li>
22816     *         <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li>
22817     *         <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li>
22818     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li>
22819     *         <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li>
22820     *         <li>{@link #DRAG_FLAG_OPAQUE}</li>
22821     *     </ul>
22822     * @return {@code true} if the method completes successfully, or
22823     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
22824     * do a drag, and so no drag operation is in progress.
22825     */
22826    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
22827            Object myLocalState, int flags) {
22828        if (ViewDebug.DEBUG_DRAG) {
22829            Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
22830        }
22831        if (mAttachInfo == null) {
22832            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
22833            return false;
22834        }
22835
22836        if (data != null) {
22837            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
22838        }
22839
22840        boolean okay = false;
22841
22842        Point shadowSize = new Point();
22843        Point shadowTouchPoint = new Point();
22844        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
22845
22846        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
22847                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
22848            throw new IllegalStateException("Drag shadow dimensions must not be negative");
22849        }
22850
22851        if (ViewDebug.DEBUG_DRAG) {
22852            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
22853                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
22854        }
22855        if (mAttachInfo.mDragSurface != null) {
22856            mAttachInfo.mDragSurface.release();
22857        }
22858        mAttachInfo.mDragSurface = new Surface();
22859        try {
22860            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
22861                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
22862            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
22863                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
22864            if (mAttachInfo.mDragToken != null) {
22865                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22866                try {
22867                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22868                    shadowBuilder.onDrawShadow(canvas);
22869                } finally {
22870                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22871                }
22872
22873                final ViewRootImpl root = getViewRootImpl();
22874
22875                // Cache the local state object for delivery with DragEvents
22876                root.setLocalDragState(myLocalState);
22877
22878                // repurpose 'shadowSize' for the last touch point
22879                root.getLastTouchPoint(shadowSize);
22880
22881                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
22882                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
22883                        shadowTouchPoint.x, shadowTouchPoint.y, data);
22884                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
22885            }
22886        } catch (Exception e) {
22887            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
22888            mAttachInfo.mDragSurface.destroy();
22889            mAttachInfo.mDragSurface = null;
22890        }
22891
22892        return okay;
22893    }
22894
22895    /**
22896     * Cancels an ongoing drag and drop operation.
22897     * <p>
22898     * A {@link android.view.DragEvent} object with
22899     * {@link android.view.DragEvent#getAction()} value of
22900     * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and
22901     * {@link android.view.DragEvent#getResult()} value of {@code false}
22902     * will be sent to every
22903     * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED}
22904     * even if they are not currently visible.
22905     * </p>
22906     * <p>
22907     * This method can be called on any View in the same window as the View on which
22908     * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop}
22909     * was called.
22910     * </p>
22911     */
22912    public final void cancelDragAndDrop() {
22913        if (ViewDebug.DEBUG_DRAG) {
22914            Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
22915        }
22916        if (mAttachInfo == null) {
22917            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
22918            return;
22919        }
22920        if (mAttachInfo.mDragToken != null) {
22921            try {
22922                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
22923            } catch (Exception e) {
22924                Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
22925            }
22926            mAttachInfo.mDragToken = null;
22927        } else {
22928            Log.e(VIEW_LOG_TAG, "No active drag to cancel");
22929        }
22930    }
22931
22932    /**
22933     * Updates the drag shadow for the ongoing drag and drop operation.
22934     *
22935     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
22936     * new drag shadow.
22937     */
22938    public final void updateDragShadow(DragShadowBuilder shadowBuilder) {
22939        if (ViewDebug.DEBUG_DRAG) {
22940            Log.d(VIEW_LOG_TAG, "updateDragShadow");
22941        }
22942        if (mAttachInfo == null) {
22943            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
22944            return;
22945        }
22946        if (mAttachInfo.mDragToken != null) {
22947            try {
22948                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
22949                try {
22950                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
22951                    shadowBuilder.onDrawShadow(canvas);
22952                } finally {
22953                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
22954                }
22955            } catch (Exception e) {
22956                Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e);
22957            }
22958        } else {
22959            Log.e(VIEW_LOG_TAG, "No active drag");
22960        }
22961    }
22962
22963    /**
22964     * Starts a move from {startX, startY}, the amount of the movement will be the offset
22965     * between {startX, startY} and the new cursor positon.
22966     * @param startX horizontal coordinate where the move started.
22967     * @param startY vertical coordinate where the move started.
22968     * @return whether moving was started successfully.
22969     * @hide
22970     */
22971    public final boolean startMovingTask(float startX, float startY) {
22972        if (ViewDebug.DEBUG_POSITIONING) {
22973            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
22974        }
22975        try {
22976            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
22977        } catch (RemoteException e) {
22978            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
22979        }
22980        return false;
22981    }
22982
22983    /**
22984     * Handles drag events sent by the system following a call to
22985     * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int)
22986     * startDragAndDrop()}.
22987     *<p>
22988     * When the system calls this method, it passes a
22989     * {@link android.view.DragEvent} object. A call to
22990     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
22991     * in DragEvent. The method uses these to determine what is happening in the drag and drop
22992     * operation.
22993     * @param event The {@link android.view.DragEvent} sent by the system.
22994     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
22995     * in DragEvent, indicating the type of drag event represented by this object.
22996     * @return {@code true} if the method was successful, otherwise {@code false}.
22997     * <p>
22998     *  The method should return {@code true} in response to an action type of
22999     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
23000     *  operation.
23001     * </p>
23002     * <p>
23003     *  The method should also return {@code true} in response to an action type of
23004     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
23005     *  {@code false} if it didn't.
23006     * </p>
23007     * <p>
23008     *  For all other events, the return value is ignored.
23009     * </p>
23010     */
23011    public boolean onDragEvent(DragEvent event) {
23012        return false;
23013    }
23014
23015    // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps.
23016    boolean dispatchDragEnterExitInPreN(DragEvent event) {
23017        return callDragEventHandler(event);
23018    }
23019
23020    /**
23021     * Detects if this View is enabled and has a drag event listener.
23022     * If both are true, then it calls the drag event listener with the
23023     * {@link android.view.DragEvent} it received. If the drag event listener returns
23024     * {@code true}, then dispatchDragEvent() returns {@code true}.
23025     * <p>
23026     * For all other cases, the method calls the
23027     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
23028     * method and returns its result.
23029     * </p>
23030     * <p>
23031     * This ensures that a drag event is always consumed, even if the View does not have a drag
23032     * event listener. However, if the View has a listener and the listener returns true, then
23033     * onDragEvent() is not called.
23034     * </p>
23035     */
23036    public boolean dispatchDragEvent(DragEvent event) {
23037        event.mEventHandlerWasCalled = true;
23038        if (event.mAction == DragEvent.ACTION_DRAG_LOCATION ||
23039            event.mAction == DragEvent.ACTION_DROP) {
23040            // About to deliver an event with coordinates to this view. Notify that now this view
23041            // has drag focus. This will send exit/enter events as needed.
23042            getViewRootImpl().setDragFocus(this, event);
23043        }
23044        return callDragEventHandler(event);
23045    }
23046
23047    final boolean callDragEventHandler(DragEvent event) {
23048        final boolean result;
23049
23050        ListenerInfo li = mListenerInfo;
23051        //noinspection SimplifiableIfStatement
23052        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
23053                && li.mOnDragListener.onDrag(this, event)) {
23054            result = true;
23055        } else {
23056            result = onDragEvent(event);
23057        }
23058
23059        switch (event.mAction) {
23060            case DragEvent.ACTION_DRAG_ENTERED: {
23061                mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED;
23062                refreshDrawableState();
23063            } break;
23064            case DragEvent.ACTION_DRAG_EXITED: {
23065                mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED;
23066                refreshDrawableState();
23067            } break;
23068            case DragEvent.ACTION_DRAG_ENDED: {
23069                mPrivateFlags2 &= ~View.DRAG_MASK;
23070                refreshDrawableState();
23071            } break;
23072        }
23073
23074        return result;
23075    }
23076
23077    boolean canAcceptDrag() {
23078        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
23079    }
23080
23081    /**
23082     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
23083     * it is ever exposed at all.
23084     * @hide
23085     */
23086    public void onCloseSystemDialogs(String reason) {
23087    }
23088
23089    /**
23090     * Given a Drawable whose bounds have been set to draw into this view,
23091     * update a Region being computed for
23092     * {@link #gatherTransparentRegion(android.graphics.Region)} so
23093     * that any non-transparent parts of the Drawable are removed from the
23094     * given transparent region.
23095     *
23096     * @param dr The Drawable whose transparency is to be applied to the region.
23097     * @param region A Region holding the current transparency information,
23098     * where any parts of the region that are set are considered to be
23099     * transparent.  On return, this region will be modified to have the
23100     * transparency information reduced by the corresponding parts of the
23101     * Drawable that are not transparent.
23102     * {@hide}
23103     */
23104    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
23105        if (DBG) {
23106            Log.i("View", "Getting transparent region for: " + this);
23107        }
23108        final Region r = dr.getTransparentRegion();
23109        final Rect db = dr.getBounds();
23110        final AttachInfo attachInfo = mAttachInfo;
23111        if (r != null && attachInfo != null) {
23112            final int w = getRight()-getLeft();
23113            final int h = getBottom()-getTop();
23114            if (db.left > 0) {
23115                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
23116                r.op(0, 0, db.left, h, Region.Op.UNION);
23117            }
23118            if (db.right < w) {
23119                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
23120                r.op(db.right, 0, w, h, Region.Op.UNION);
23121            }
23122            if (db.top > 0) {
23123                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
23124                r.op(0, 0, w, db.top, Region.Op.UNION);
23125            }
23126            if (db.bottom < h) {
23127                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
23128                r.op(0, db.bottom, w, h, Region.Op.UNION);
23129            }
23130            final int[] location = attachInfo.mTransparentLocation;
23131            getLocationInWindow(location);
23132            r.translate(location[0], location[1]);
23133            region.op(r, Region.Op.INTERSECT);
23134        } else {
23135            region.op(db, Region.Op.DIFFERENCE);
23136        }
23137    }
23138
23139    private void checkForLongClick(int delayOffset, float x, float y) {
23140        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
23141            mHasPerformedLongPress = false;
23142
23143            if (mPendingCheckForLongPress == null) {
23144                mPendingCheckForLongPress = new CheckForLongPress();
23145            }
23146            mPendingCheckForLongPress.setAnchor(x, y);
23147            mPendingCheckForLongPress.rememberWindowAttachCount();
23148            mPendingCheckForLongPress.rememberPressedState();
23149            postDelayed(mPendingCheckForLongPress,
23150                    ViewConfiguration.getLongPressTimeout() - delayOffset);
23151        }
23152    }
23153
23154    /**
23155     * Inflate a view from an XML resource.  This convenience method wraps the {@link
23156     * LayoutInflater} class, which provides a full range of options for view inflation.
23157     *
23158     * @param context The Context object for your activity or application.
23159     * @param resource The resource ID to inflate
23160     * @param root A view group that will be the parent.  Used to properly inflate the
23161     * layout_* parameters.
23162     * @see LayoutInflater
23163     */
23164    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
23165        LayoutInflater factory = LayoutInflater.from(context);
23166        return factory.inflate(resource, root);
23167    }
23168
23169    /**
23170     * Scroll the view with standard behavior for scrolling beyond the normal
23171     * content boundaries. Views that call this method should override
23172     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
23173     * results of an over-scroll operation.
23174     *
23175     * Views can use this method to handle any touch or fling-based scrolling.
23176     *
23177     * @param deltaX Change in X in pixels
23178     * @param deltaY Change in Y in pixels
23179     * @param scrollX Current X scroll value in pixels before applying deltaX
23180     * @param scrollY Current Y scroll value in pixels before applying deltaY
23181     * @param scrollRangeX Maximum content scroll range along the X axis
23182     * @param scrollRangeY Maximum content scroll range along the Y axis
23183     * @param maxOverScrollX Number of pixels to overscroll by in either direction
23184     *          along the X axis.
23185     * @param maxOverScrollY Number of pixels to overscroll by in either direction
23186     *          along the Y axis.
23187     * @param isTouchEvent true if this scroll operation is the result of a touch event.
23188     * @return true if scrolling was clamped to an over-scroll boundary along either
23189     *          axis, false otherwise.
23190     */
23191    @SuppressWarnings({"UnusedParameters"})
23192    protected boolean overScrollBy(int deltaX, int deltaY,
23193            int scrollX, int scrollY,
23194            int scrollRangeX, int scrollRangeY,
23195            int maxOverScrollX, int maxOverScrollY,
23196            boolean isTouchEvent) {
23197        final int overScrollMode = mOverScrollMode;
23198        final boolean canScrollHorizontal =
23199                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
23200        final boolean canScrollVertical =
23201                computeVerticalScrollRange() > computeVerticalScrollExtent();
23202        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
23203                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
23204        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
23205                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
23206
23207        int newScrollX = scrollX + deltaX;
23208        if (!overScrollHorizontal) {
23209            maxOverScrollX = 0;
23210        }
23211
23212        int newScrollY = scrollY + deltaY;
23213        if (!overScrollVertical) {
23214            maxOverScrollY = 0;
23215        }
23216
23217        // Clamp values if at the limits and record
23218        final int left = -maxOverScrollX;
23219        final int right = maxOverScrollX + scrollRangeX;
23220        final int top = -maxOverScrollY;
23221        final int bottom = maxOverScrollY + scrollRangeY;
23222
23223        boolean clampedX = false;
23224        if (newScrollX > right) {
23225            newScrollX = right;
23226            clampedX = true;
23227        } else if (newScrollX < left) {
23228            newScrollX = left;
23229            clampedX = true;
23230        }
23231
23232        boolean clampedY = false;
23233        if (newScrollY > bottom) {
23234            newScrollY = bottom;
23235            clampedY = true;
23236        } else if (newScrollY < top) {
23237            newScrollY = top;
23238            clampedY = true;
23239        }
23240
23241        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
23242
23243        return clampedX || clampedY;
23244    }
23245
23246    /**
23247     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
23248     * respond to the results of an over-scroll operation.
23249     *
23250     * @param scrollX New X scroll value in pixels
23251     * @param scrollY New Y scroll value in pixels
23252     * @param clampedX True if scrollX was clamped to an over-scroll boundary
23253     * @param clampedY True if scrollY was clamped to an over-scroll boundary
23254     */
23255    protected void onOverScrolled(int scrollX, int scrollY,
23256            boolean clampedX, boolean clampedY) {
23257        // Intentionally empty.
23258    }
23259
23260    /**
23261     * Returns the over-scroll mode for this view. The result will be
23262     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23263     * (allow over-scrolling only if the view content is larger than the container),
23264     * or {@link #OVER_SCROLL_NEVER}.
23265     *
23266     * @return This view's over-scroll mode.
23267     */
23268    public int getOverScrollMode() {
23269        return mOverScrollMode;
23270    }
23271
23272    /**
23273     * Set the over-scroll mode for this view. Valid over-scroll modes are
23274     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
23275     * (allow over-scrolling only if the view content is larger than the container),
23276     * or {@link #OVER_SCROLL_NEVER}.
23277     *
23278     * Setting the over-scroll mode of a view will have an effect only if the
23279     * view is capable of scrolling.
23280     *
23281     * @param overScrollMode The new over-scroll mode for this view.
23282     */
23283    public void setOverScrollMode(int overScrollMode) {
23284        if (overScrollMode != OVER_SCROLL_ALWAYS &&
23285                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
23286                overScrollMode != OVER_SCROLL_NEVER) {
23287            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
23288        }
23289        mOverScrollMode = overScrollMode;
23290    }
23291
23292    /**
23293     * Enable or disable nested scrolling for this view.
23294     *
23295     * <p>If this property is set to true the view will be permitted to initiate nested
23296     * scrolling operations with a compatible parent view in the current hierarchy. If this
23297     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
23298     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
23299     * the nested scroll.</p>
23300     *
23301     * @param enabled true to enable nested scrolling, false to disable
23302     *
23303     * @see #isNestedScrollingEnabled()
23304     */
23305    public void setNestedScrollingEnabled(boolean enabled) {
23306        if (enabled) {
23307            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
23308        } else {
23309            stopNestedScroll();
23310            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
23311        }
23312    }
23313
23314    /**
23315     * Returns true if nested scrolling is enabled for this view.
23316     *
23317     * <p>If nested scrolling is enabled and this View class implementation supports it,
23318     * this view will act as a nested scrolling child view when applicable, forwarding data
23319     * about the scroll operation in progress to a compatible and cooperating nested scrolling
23320     * parent.</p>
23321     *
23322     * @return true if nested scrolling is enabled
23323     *
23324     * @see #setNestedScrollingEnabled(boolean)
23325     */
23326    public boolean isNestedScrollingEnabled() {
23327        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
23328                PFLAG3_NESTED_SCROLLING_ENABLED;
23329    }
23330
23331    /**
23332     * Begin a nestable scroll operation along the given axes.
23333     *
23334     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
23335     *
23336     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
23337     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
23338     * In the case of touch scrolling the nested scroll will be terminated automatically in
23339     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
23340     * In the event of programmatic scrolling the caller must explicitly call
23341     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
23342     *
23343     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
23344     * If it returns false the caller may ignore the rest of this contract until the next scroll.
23345     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
23346     *
23347     * <p>At each incremental step of the scroll the caller should invoke
23348     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
23349     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
23350     * parent at least partially consumed the scroll and the caller should adjust the amount it
23351     * scrolls by.</p>
23352     *
23353     * <p>After applying the remainder of the scroll delta the caller should invoke
23354     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
23355     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
23356     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
23357     * </p>
23358     *
23359     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
23360     *             {@link #SCROLL_AXIS_VERTICAL}.
23361     * @return true if a cooperative parent was found and nested scrolling has been enabled for
23362     *         the current gesture.
23363     *
23364     * @see #stopNestedScroll()
23365     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23366     * @see #dispatchNestedScroll(int, int, int, int, int[])
23367     */
23368    public boolean startNestedScroll(int axes) {
23369        if (hasNestedScrollingParent()) {
23370            // Already in progress
23371            return true;
23372        }
23373        if (isNestedScrollingEnabled()) {
23374            ViewParent p = getParent();
23375            View child = this;
23376            while (p != null) {
23377                try {
23378                    if (p.onStartNestedScroll(child, this, axes)) {
23379                        mNestedScrollingParent = p;
23380                        p.onNestedScrollAccepted(child, this, axes);
23381                        return true;
23382                    }
23383                } catch (AbstractMethodError e) {
23384                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
23385                            "method onStartNestedScroll", e);
23386                    // Allow the search upward to continue
23387                }
23388                if (p instanceof View) {
23389                    child = (View) p;
23390                }
23391                p = p.getParent();
23392            }
23393        }
23394        return false;
23395    }
23396
23397    /**
23398     * Stop a nested scroll in progress.
23399     *
23400     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
23401     *
23402     * @see #startNestedScroll(int)
23403     */
23404    public void stopNestedScroll() {
23405        if (mNestedScrollingParent != null) {
23406            mNestedScrollingParent.onStopNestedScroll(this);
23407            mNestedScrollingParent = null;
23408        }
23409    }
23410
23411    /**
23412     * Returns true if this view has a nested scrolling parent.
23413     *
23414     * <p>The presence of a nested scrolling parent indicates that this view has initiated
23415     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
23416     *
23417     * @return whether this view has a nested scrolling parent
23418     */
23419    public boolean hasNestedScrollingParent() {
23420        return mNestedScrollingParent != null;
23421    }
23422
23423    /**
23424     * Dispatch one step of a nested scroll in progress.
23425     *
23426     * <p>Implementations of views that support nested scrolling should call this to report
23427     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
23428     * is not currently in progress or nested scrolling is not
23429     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
23430     *
23431     * <p>Compatible View implementations should also call
23432     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
23433     * consuming a component of the scroll event themselves.</p>
23434     *
23435     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
23436     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
23437     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
23438     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
23439     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23440     *                       in local view coordinates of this view from before this operation
23441     *                       to after it completes. View implementations may use this to adjust
23442     *                       expected input coordinate tracking.
23443     * @return true if the event was dispatched, false if it could not be dispatched.
23444     * @see #dispatchNestedPreScroll(int, int, int[], int[])
23445     */
23446    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
23447            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
23448        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23449            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
23450                int startX = 0;
23451                int startY = 0;
23452                if (offsetInWindow != null) {
23453                    getLocationInWindow(offsetInWindow);
23454                    startX = offsetInWindow[0];
23455                    startY = offsetInWindow[1];
23456                }
23457
23458                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
23459                        dxUnconsumed, dyUnconsumed);
23460
23461                if (offsetInWindow != null) {
23462                    getLocationInWindow(offsetInWindow);
23463                    offsetInWindow[0] -= startX;
23464                    offsetInWindow[1] -= startY;
23465                }
23466                return true;
23467            } else if (offsetInWindow != null) {
23468                // No motion, no dispatch. Keep offsetInWindow up to date.
23469                offsetInWindow[0] = 0;
23470                offsetInWindow[1] = 0;
23471            }
23472        }
23473        return false;
23474    }
23475
23476    /**
23477     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
23478     *
23479     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
23480     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
23481     * scrolling operation to consume some or all of the scroll operation before the child view
23482     * consumes it.</p>
23483     *
23484     * @param dx Horizontal scroll distance in pixels
23485     * @param dy Vertical scroll distance in pixels
23486     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
23487     *                 and consumed[1] the consumed dy.
23488     * @param offsetInWindow Optional. If not null, on return this will contain the offset
23489     *                       in local view coordinates of this view from before this operation
23490     *                       to after it completes. View implementations may use this to adjust
23491     *                       expected input coordinate tracking.
23492     * @return true if the parent consumed some or all of the scroll delta
23493     * @see #dispatchNestedScroll(int, int, int, int, int[])
23494     */
23495    public boolean dispatchNestedPreScroll(int dx, int dy,
23496            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
23497        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23498            if (dx != 0 || dy != 0) {
23499                int startX = 0;
23500                int startY = 0;
23501                if (offsetInWindow != null) {
23502                    getLocationInWindow(offsetInWindow);
23503                    startX = offsetInWindow[0];
23504                    startY = offsetInWindow[1];
23505                }
23506
23507                if (consumed == null) {
23508                    if (mTempNestedScrollConsumed == null) {
23509                        mTempNestedScrollConsumed = new int[2];
23510                    }
23511                    consumed = mTempNestedScrollConsumed;
23512                }
23513                consumed[0] = 0;
23514                consumed[1] = 0;
23515                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
23516
23517                if (offsetInWindow != null) {
23518                    getLocationInWindow(offsetInWindow);
23519                    offsetInWindow[0] -= startX;
23520                    offsetInWindow[1] -= startY;
23521                }
23522                return consumed[0] != 0 || consumed[1] != 0;
23523            } else if (offsetInWindow != null) {
23524                offsetInWindow[0] = 0;
23525                offsetInWindow[1] = 0;
23526            }
23527        }
23528        return false;
23529    }
23530
23531    /**
23532     * Dispatch a fling to a nested scrolling parent.
23533     *
23534     * <p>This method should be used to indicate that a nested scrolling child has detected
23535     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
23536     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
23537     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
23538     * along a scrollable axis.</p>
23539     *
23540     * <p>If a nested scrolling child view would normally fling but it is at the edge of
23541     * its own content, it can use this method to delegate the fling to its nested scrolling
23542     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
23543     *
23544     * @param velocityX Horizontal fling velocity in pixels per second
23545     * @param velocityY Vertical fling velocity in pixels per second
23546     * @param consumed true if the child consumed the fling, false otherwise
23547     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
23548     */
23549    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
23550        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23551            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
23552        }
23553        return false;
23554    }
23555
23556    /**
23557     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
23558     *
23559     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
23560     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
23561     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
23562     * before the child view consumes it. If this method returns <code>true</code>, a nested
23563     * parent view consumed the fling and this view should not scroll as a result.</p>
23564     *
23565     * <p>For a better user experience, only one view in a nested scrolling chain should consume
23566     * the fling at a time. If a parent view consumed the fling this method will return false.
23567     * Custom view implementations should account for this in two ways:</p>
23568     *
23569     * <ul>
23570     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
23571     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
23572     *     position regardless.</li>
23573     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
23574     *     even to settle back to a valid idle position.</li>
23575     * </ul>
23576     *
23577     * <p>Views should also not offer fling velocities to nested parent views along an axis
23578     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
23579     * should not offer a horizontal fling velocity to its parents since scrolling along that
23580     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
23581     *
23582     * @param velocityX Horizontal fling velocity in pixels per second
23583     * @param velocityY Vertical fling velocity in pixels per second
23584     * @return true if a nested scrolling parent consumed the fling
23585     */
23586    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
23587        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
23588            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
23589        }
23590        return false;
23591    }
23592
23593    /**
23594     * Gets a scale factor that determines the distance the view should scroll
23595     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
23596     * @return The vertical scroll scale factor.
23597     * @hide
23598     */
23599    protected float getVerticalScrollFactor() {
23600        if (mVerticalScrollFactor == 0) {
23601            TypedValue outValue = new TypedValue();
23602            if (!mContext.getTheme().resolveAttribute(
23603                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
23604                throw new IllegalStateException(
23605                        "Expected theme to define listPreferredItemHeight.");
23606            }
23607            mVerticalScrollFactor = outValue.getDimension(
23608                    mContext.getResources().getDisplayMetrics());
23609        }
23610        return mVerticalScrollFactor;
23611    }
23612
23613    /**
23614     * Gets a scale factor that determines the distance the view should scroll
23615     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
23616     * @return The horizontal scroll scale factor.
23617     * @hide
23618     */
23619    protected float getHorizontalScrollFactor() {
23620        // TODO: Should use something else.
23621        return getVerticalScrollFactor();
23622    }
23623
23624    /**
23625     * Return the value specifying the text direction or policy that was set with
23626     * {@link #setTextDirection(int)}.
23627     *
23628     * @return the defined text direction. It can be one of:
23629     *
23630     * {@link #TEXT_DIRECTION_INHERIT},
23631     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23632     * {@link #TEXT_DIRECTION_ANY_RTL},
23633     * {@link #TEXT_DIRECTION_LTR},
23634     * {@link #TEXT_DIRECTION_RTL},
23635     * {@link #TEXT_DIRECTION_LOCALE},
23636     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23637     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23638     *
23639     * @attr ref android.R.styleable#View_textDirection
23640     *
23641     * @hide
23642     */
23643    @ViewDebug.ExportedProperty(category = "text", mapping = {
23644            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23645            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23646            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23647            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23648            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23649            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23650            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23651            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23652    })
23653    public int getRawTextDirection() {
23654        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
23655    }
23656
23657    /**
23658     * Set the text direction.
23659     *
23660     * @param textDirection the direction to set. Should be one of:
23661     *
23662     * {@link #TEXT_DIRECTION_INHERIT},
23663     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23664     * {@link #TEXT_DIRECTION_ANY_RTL},
23665     * {@link #TEXT_DIRECTION_LTR},
23666     * {@link #TEXT_DIRECTION_RTL},
23667     * {@link #TEXT_DIRECTION_LOCALE}
23668     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23669     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
23670     *
23671     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
23672     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
23673     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
23674     *
23675     * @attr ref android.R.styleable#View_textDirection
23676     */
23677    public void setTextDirection(int textDirection) {
23678        if (getRawTextDirection() != textDirection) {
23679            // Reset the current text direction and the resolved one
23680            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
23681            resetResolvedTextDirection();
23682            // Set the new text direction
23683            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
23684            // Do resolution
23685            resolveTextDirection();
23686            // Notify change
23687            onRtlPropertiesChanged(getLayoutDirection());
23688            // Refresh
23689            requestLayout();
23690            invalidate(true);
23691        }
23692    }
23693
23694    /**
23695     * Return the resolved text direction.
23696     *
23697     * @return the resolved text direction. Returns one of:
23698     *
23699     * {@link #TEXT_DIRECTION_FIRST_STRONG},
23700     * {@link #TEXT_DIRECTION_ANY_RTL},
23701     * {@link #TEXT_DIRECTION_LTR},
23702     * {@link #TEXT_DIRECTION_RTL},
23703     * {@link #TEXT_DIRECTION_LOCALE},
23704     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
23705     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
23706     *
23707     * @attr ref android.R.styleable#View_textDirection
23708     */
23709    @ViewDebug.ExportedProperty(category = "text", mapping = {
23710            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
23711            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
23712            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
23713            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
23714            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
23715            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
23716            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
23717            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
23718    })
23719    public int getTextDirection() {
23720        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
23721    }
23722
23723    /**
23724     * Resolve the text direction.
23725     *
23726     * @return true if resolution has been done, false otherwise.
23727     *
23728     * @hide
23729     */
23730    public boolean resolveTextDirection() {
23731        // Reset any previous text direction resolution
23732        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23733
23734        if (hasRtlSupport()) {
23735            // Set resolved text direction flag depending on text direction flag
23736            final int textDirection = getRawTextDirection();
23737            switch(textDirection) {
23738                case TEXT_DIRECTION_INHERIT:
23739                    if (!canResolveTextDirection()) {
23740                        // We cannot do the resolution if there is no parent, so use the default one
23741                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23742                        // Resolution will need to happen again later
23743                        return false;
23744                    }
23745
23746                    // Parent has not yet resolved, so we still return the default
23747                    try {
23748                        if (!mParent.isTextDirectionResolved()) {
23749                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23750                            // Resolution will need to happen again later
23751                            return false;
23752                        }
23753                    } catch (AbstractMethodError e) {
23754                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23755                                " does not fully implement ViewParent", e);
23756                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
23757                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23758                        return true;
23759                    }
23760
23761                    // Set current resolved direction to the same value as the parent's one
23762                    int parentResolvedDirection;
23763                    try {
23764                        parentResolvedDirection = mParent.getTextDirection();
23765                    } catch (AbstractMethodError e) {
23766                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23767                                " does not fully implement ViewParent", e);
23768                        parentResolvedDirection = TEXT_DIRECTION_LTR;
23769                    }
23770                    switch (parentResolvedDirection) {
23771                        case TEXT_DIRECTION_FIRST_STRONG:
23772                        case TEXT_DIRECTION_ANY_RTL:
23773                        case TEXT_DIRECTION_LTR:
23774                        case TEXT_DIRECTION_RTL:
23775                        case TEXT_DIRECTION_LOCALE:
23776                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
23777                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
23778                            mPrivateFlags2 |=
23779                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23780                            break;
23781                        default:
23782                            // Default resolved direction is "first strong" heuristic
23783                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23784                    }
23785                    break;
23786                case TEXT_DIRECTION_FIRST_STRONG:
23787                case TEXT_DIRECTION_ANY_RTL:
23788                case TEXT_DIRECTION_LTR:
23789                case TEXT_DIRECTION_RTL:
23790                case TEXT_DIRECTION_LOCALE:
23791                case TEXT_DIRECTION_FIRST_STRONG_LTR:
23792                case TEXT_DIRECTION_FIRST_STRONG_RTL:
23793                    // Resolved direction is the same as text direction
23794                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
23795                    break;
23796                default:
23797                    // Default resolved direction is "first strong" heuristic
23798                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23799            }
23800        } else {
23801            // Default resolved direction is "first strong" heuristic
23802            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23803        }
23804
23805        // Set to resolved
23806        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
23807        return true;
23808    }
23809
23810    /**
23811     * Check if text direction resolution can be done.
23812     *
23813     * @return true if text direction resolution can be done otherwise return false.
23814     */
23815    public boolean canResolveTextDirection() {
23816        switch (getRawTextDirection()) {
23817            case TEXT_DIRECTION_INHERIT:
23818                if (mParent != null) {
23819                    try {
23820                        return mParent.canResolveTextDirection();
23821                    } catch (AbstractMethodError e) {
23822                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23823                                " does not fully implement ViewParent", e);
23824                    }
23825                }
23826                return false;
23827
23828            default:
23829                return true;
23830        }
23831    }
23832
23833    /**
23834     * Reset resolved text direction. Text direction will be resolved during a call to
23835     * {@link #onMeasure(int, int)}.
23836     *
23837     * @hide
23838     */
23839    public void resetResolvedTextDirection() {
23840        // Reset any previous text direction resolution
23841        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
23842        // Set to default value
23843        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
23844    }
23845
23846    /**
23847     * @return true if text direction is inherited.
23848     *
23849     * @hide
23850     */
23851    public boolean isTextDirectionInherited() {
23852        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
23853    }
23854
23855    /**
23856     * @return true if text direction is resolved.
23857     */
23858    public boolean isTextDirectionResolved() {
23859        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
23860    }
23861
23862    /**
23863     * Return the value specifying the text alignment or policy that was set with
23864     * {@link #setTextAlignment(int)}.
23865     *
23866     * @return the defined text alignment. It can be one of:
23867     *
23868     * {@link #TEXT_ALIGNMENT_INHERIT},
23869     * {@link #TEXT_ALIGNMENT_GRAVITY},
23870     * {@link #TEXT_ALIGNMENT_CENTER},
23871     * {@link #TEXT_ALIGNMENT_TEXT_START},
23872     * {@link #TEXT_ALIGNMENT_TEXT_END},
23873     * {@link #TEXT_ALIGNMENT_VIEW_START},
23874     * {@link #TEXT_ALIGNMENT_VIEW_END}
23875     *
23876     * @attr ref android.R.styleable#View_textAlignment
23877     *
23878     * @hide
23879     */
23880    @ViewDebug.ExportedProperty(category = "text", mapping = {
23881            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23882            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23883            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23884            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23885            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23886            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23887            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23888    })
23889    @TextAlignment
23890    public int getRawTextAlignment() {
23891        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
23892    }
23893
23894    /**
23895     * Set the text alignment.
23896     *
23897     * @param textAlignment The text alignment to set. Should be one of
23898     *
23899     * {@link #TEXT_ALIGNMENT_INHERIT},
23900     * {@link #TEXT_ALIGNMENT_GRAVITY},
23901     * {@link #TEXT_ALIGNMENT_CENTER},
23902     * {@link #TEXT_ALIGNMENT_TEXT_START},
23903     * {@link #TEXT_ALIGNMENT_TEXT_END},
23904     * {@link #TEXT_ALIGNMENT_VIEW_START},
23905     * {@link #TEXT_ALIGNMENT_VIEW_END}
23906     *
23907     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
23908     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
23909     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
23910     *
23911     * @attr ref android.R.styleable#View_textAlignment
23912     */
23913    public void setTextAlignment(@TextAlignment int textAlignment) {
23914        if (textAlignment != getRawTextAlignment()) {
23915            // Reset the current and resolved text alignment
23916            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
23917            resetResolvedTextAlignment();
23918            // Set the new text alignment
23919            mPrivateFlags2 |=
23920                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
23921            // Do resolution
23922            resolveTextAlignment();
23923            // Notify change
23924            onRtlPropertiesChanged(getLayoutDirection());
23925            // Refresh
23926            requestLayout();
23927            invalidate(true);
23928        }
23929    }
23930
23931    /**
23932     * Return the resolved text alignment.
23933     *
23934     * @return the resolved text alignment. Returns one of:
23935     *
23936     * {@link #TEXT_ALIGNMENT_GRAVITY},
23937     * {@link #TEXT_ALIGNMENT_CENTER},
23938     * {@link #TEXT_ALIGNMENT_TEXT_START},
23939     * {@link #TEXT_ALIGNMENT_TEXT_END},
23940     * {@link #TEXT_ALIGNMENT_VIEW_START},
23941     * {@link #TEXT_ALIGNMENT_VIEW_END}
23942     *
23943     * @attr ref android.R.styleable#View_textAlignment
23944     */
23945    @ViewDebug.ExportedProperty(category = "text", mapping = {
23946            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
23947            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
23948            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
23949            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
23950            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
23951            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
23952            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
23953    })
23954    @TextAlignment
23955    public int getTextAlignment() {
23956        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
23957                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
23958    }
23959
23960    /**
23961     * Resolve the text alignment.
23962     *
23963     * @return true if resolution has been done, false otherwise.
23964     *
23965     * @hide
23966     */
23967    public boolean resolveTextAlignment() {
23968        // Reset any previous text alignment resolution
23969        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
23970
23971        if (hasRtlSupport()) {
23972            // Set resolved text alignment flag depending on text alignment flag
23973            final int textAlignment = getRawTextAlignment();
23974            switch (textAlignment) {
23975                case TEXT_ALIGNMENT_INHERIT:
23976                    // Check if we can resolve the text alignment
23977                    if (!canResolveTextAlignment()) {
23978                        // We cannot do the resolution if there is no parent so use the default
23979                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23980                        // Resolution will need to happen again later
23981                        return false;
23982                    }
23983
23984                    // Parent has not yet resolved, so we still return the default
23985                    try {
23986                        if (!mParent.isTextAlignmentResolved()) {
23987                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23988                            // Resolution will need to happen again later
23989                            return false;
23990                        }
23991                    } catch (AbstractMethodError e) {
23992                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
23993                                " does not fully implement ViewParent", e);
23994                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
23995                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
23996                        return true;
23997                    }
23998
23999                    int parentResolvedTextAlignment;
24000                    try {
24001                        parentResolvedTextAlignment = mParent.getTextAlignment();
24002                    } catch (AbstractMethodError e) {
24003                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24004                                " does not fully implement ViewParent", e);
24005                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
24006                    }
24007                    switch (parentResolvedTextAlignment) {
24008                        case TEXT_ALIGNMENT_GRAVITY:
24009                        case TEXT_ALIGNMENT_TEXT_START:
24010                        case TEXT_ALIGNMENT_TEXT_END:
24011                        case TEXT_ALIGNMENT_CENTER:
24012                        case TEXT_ALIGNMENT_VIEW_START:
24013                        case TEXT_ALIGNMENT_VIEW_END:
24014                            // Resolved text alignment is the same as the parent resolved
24015                            // text alignment
24016                            mPrivateFlags2 |=
24017                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
24018                            break;
24019                        default:
24020                            // Use default resolved text alignment
24021                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24022                    }
24023                    break;
24024                case TEXT_ALIGNMENT_GRAVITY:
24025                case TEXT_ALIGNMENT_TEXT_START:
24026                case TEXT_ALIGNMENT_TEXT_END:
24027                case TEXT_ALIGNMENT_CENTER:
24028                case TEXT_ALIGNMENT_VIEW_START:
24029                case TEXT_ALIGNMENT_VIEW_END:
24030                    // Resolved text alignment is the same as text alignment
24031                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
24032                    break;
24033                default:
24034                    // Use default resolved text alignment
24035                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24036            }
24037        } else {
24038            // Use default resolved text alignment
24039            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24040        }
24041
24042        // Set the resolved
24043        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
24044        return true;
24045    }
24046
24047    /**
24048     * Check if text alignment resolution can be done.
24049     *
24050     * @return true if text alignment resolution can be done otherwise return false.
24051     */
24052    public boolean canResolveTextAlignment() {
24053        switch (getRawTextAlignment()) {
24054            case TEXT_DIRECTION_INHERIT:
24055                if (mParent != null) {
24056                    try {
24057                        return mParent.canResolveTextAlignment();
24058                    } catch (AbstractMethodError e) {
24059                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
24060                                " does not fully implement ViewParent", e);
24061                    }
24062                }
24063                return false;
24064
24065            default:
24066                return true;
24067        }
24068    }
24069
24070    /**
24071     * Reset resolved text alignment. Text alignment will be resolved during a call to
24072     * {@link #onMeasure(int, int)}.
24073     *
24074     * @hide
24075     */
24076    public void resetResolvedTextAlignment() {
24077        // Reset any previous text alignment resolution
24078        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
24079        // Set to default
24080        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
24081    }
24082
24083    /**
24084     * @return true if text alignment is inherited.
24085     *
24086     * @hide
24087     */
24088    public boolean isTextAlignmentInherited() {
24089        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
24090    }
24091
24092    /**
24093     * @return true if text alignment is resolved.
24094     */
24095    public boolean isTextAlignmentResolved() {
24096        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
24097    }
24098
24099    /**
24100     * Generate a value suitable for use in {@link #setId(int)}.
24101     * This value will not collide with ID values generated at build time by aapt for R.id.
24102     *
24103     * @return a generated ID value
24104     */
24105    public static int generateViewId() {
24106        for (;;) {
24107            final int result = sNextGeneratedId.get();
24108            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
24109            int newValue = result + 1;
24110            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
24111            if (sNextGeneratedId.compareAndSet(result, newValue)) {
24112                return result;
24113            }
24114        }
24115    }
24116
24117    private static boolean isViewIdGenerated(int id) {
24118        return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0;
24119    }
24120
24121    /**
24122     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
24123     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
24124     *                           a normal View or a ViewGroup with
24125     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
24126     * @hide
24127     */
24128    public void captureTransitioningViews(List<View> transitioningViews) {
24129        if (getVisibility() == View.VISIBLE) {
24130            transitioningViews.add(this);
24131        }
24132    }
24133
24134    /**
24135     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
24136     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
24137     * @hide
24138     */
24139    public void findNamedViews(Map<String, View> namedElements) {
24140        if (getVisibility() == VISIBLE || mGhostView != null) {
24141            String transitionName = getTransitionName();
24142            if (transitionName != null) {
24143                namedElements.put(transitionName, this);
24144            }
24145        }
24146    }
24147
24148    /**
24149     * Returns the pointer icon for the motion event, or null if it doesn't specify the icon.
24150     * The default implementation does not care the location or event types, but some subclasses
24151     * may use it (such as WebViews).
24152     * @param event The MotionEvent from a mouse
24153     * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}.
24154     *                     This will be between 0 and {@link MotionEvent#getPointerCount()}.
24155     * @see PointerIcon
24156     */
24157    public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
24158        final float x = event.getX(pointerIndex);
24159        final float y = event.getY(pointerIndex);
24160        if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) {
24161            return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW);
24162        }
24163        return mPointerIcon;
24164    }
24165
24166    /**
24167     * Set the pointer icon for the current view.
24168     * Passing {@code null} will restore the pointer icon to its default value.
24169     * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers.
24170     */
24171    public void setPointerIcon(PointerIcon pointerIcon) {
24172        mPointerIcon = pointerIcon;
24173        if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) {
24174            return;
24175        }
24176        try {
24177            mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow);
24178        } catch (RemoteException e) {
24179        }
24180    }
24181
24182    /**
24183     * Gets the pointer icon for the current view.
24184     */
24185    public PointerIcon getPointerIcon() {
24186        return mPointerIcon;
24187    }
24188
24189    /**
24190     * Checks pointer capture status.
24191     *
24192     * @return true if the view has pointer capture.
24193     * @see #requestPointerCapture()
24194     * @see #hasPointerCapture()
24195     */
24196    public boolean hasPointerCapture() {
24197        final ViewRootImpl viewRootImpl = getViewRootImpl();
24198        if (viewRootImpl == null) {
24199            return false;
24200        }
24201        return viewRootImpl.hasPointerCapture();
24202    }
24203
24204    /**
24205     * Requests pointer capture mode.
24206     * <p>
24207     * When the window has pointer capture, the mouse pointer icon will disappear and will not
24208     * change its position. Further mouse will be dispatched with the source
24209     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
24210     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
24211     * (touchscreens, or stylus) will not be affected.
24212     * <p>
24213     * If the window already has pointer capture, this call does nothing.
24214     * <p>
24215     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
24216     * automatically when the window loses focus.
24217     *
24218     * @see #releasePointerCapture()
24219     * @see #hasPointerCapture()
24220     */
24221    public void requestPointerCapture() {
24222        final ViewRootImpl viewRootImpl = getViewRootImpl();
24223        if (viewRootImpl != null) {
24224            viewRootImpl.requestPointerCapture(true);
24225        }
24226    }
24227
24228
24229    /**
24230     * Releases the pointer capture.
24231     * <p>
24232     * If the window does not have pointer capture, this call will do nothing.
24233     * @see #requestPointerCapture()
24234     * @see #hasPointerCapture()
24235     */
24236    public void releasePointerCapture() {
24237        final ViewRootImpl viewRootImpl = getViewRootImpl();
24238        if (viewRootImpl != null) {
24239            viewRootImpl.requestPointerCapture(false);
24240        }
24241    }
24242
24243    /**
24244     * Called when the window has just acquired or lost pointer capture.
24245     *
24246     * @param hasCapture True if the view now has pointerCapture, false otherwise.
24247     */
24248    @CallSuper
24249    public void onPointerCaptureChange(boolean hasCapture) {
24250    }
24251
24252    /**
24253     * @see #onPointerCaptureChange
24254     */
24255    public void dispatchPointerCaptureChanged(boolean hasCapture) {
24256        onPointerCaptureChange(hasCapture);
24257    }
24258
24259    /**
24260     * Implement this method to handle captured pointer events
24261     *
24262     * @param event The captured pointer event.
24263     * @return True if the event was handled, false otherwise.
24264     * @see #requestPointerCapture()
24265     */
24266    public boolean onCapturedPointerEvent(MotionEvent event) {
24267        return false;
24268    }
24269
24270    /**
24271     * Interface definition for a callback to be invoked when a captured pointer event
24272     * is being dispatched this view. The callback will be invoked before the event is
24273     * given to the view.
24274     */
24275    public interface OnCapturedPointerListener {
24276        /**
24277         * Called when a captured pointer event is dispatched to a view.
24278         * @param view The view this event has been dispatched to.
24279         * @param event The captured event.
24280         * @return True if the listener has consumed the event, false otherwise.
24281         */
24282        boolean onCapturedPointer(View view, MotionEvent event);
24283    }
24284
24285    /**
24286     * Set a listener to receive callbacks when the pointer capture state of a view changes.
24287     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
24288     */
24289    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
24290        getListenerInfo().mOnCapturedPointerListener = l;
24291    }
24292
24293    // Properties
24294    //
24295    /**
24296     * A Property wrapper around the <code>alpha</code> functionality handled by the
24297     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
24298     */
24299    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
24300        @Override
24301        public void setValue(View object, float value) {
24302            object.setAlpha(value);
24303        }
24304
24305        @Override
24306        public Float get(View object) {
24307            return object.getAlpha();
24308        }
24309    };
24310
24311    /**
24312     * A Property wrapper around the <code>translationX</code> functionality handled by the
24313     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
24314     */
24315    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
24316        @Override
24317        public void setValue(View object, float value) {
24318            object.setTranslationX(value);
24319        }
24320
24321                @Override
24322        public Float get(View object) {
24323            return object.getTranslationX();
24324        }
24325    };
24326
24327    /**
24328     * A Property wrapper around the <code>translationY</code> functionality handled by the
24329     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
24330     */
24331    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
24332        @Override
24333        public void setValue(View object, float value) {
24334            object.setTranslationY(value);
24335        }
24336
24337        @Override
24338        public Float get(View object) {
24339            return object.getTranslationY();
24340        }
24341    };
24342
24343    /**
24344     * A Property wrapper around the <code>translationZ</code> functionality handled by the
24345     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
24346     */
24347    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
24348        @Override
24349        public void setValue(View object, float value) {
24350            object.setTranslationZ(value);
24351        }
24352
24353        @Override
24354        public Float get(View object) {
24355            return object.getTranslationZ();
24356        }
24357    };
24358
24359    /**
24360     * A Property wrapper around the <code>x</code> functionality handled by the
24361     * {@link View#setX(float)} and {@link View#getX()} methods.
24362     */
24363    public static final Property<View, Float> X = new FloatProperty<View>("x") {
24364        @Override
24365        public void setValue(View object, float value) {
24366            object.setX(value);
24367        }
24368
24369        @Override
24370        public Float get(View object) {
24371            return object.getX();
24372        }
24373    };
24374
24375    /**
24376     * A Property wrapper around the <code>y</code> functionality handled by the
24377     * {@link View#setY(float)} and {@link View#getY()} methods.
24378     */
24379    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
24380        @Override
24381        public void setValue(View object, float value) {
24382            object.setY(value);
24383        }
24384
24385        @Override
24386        public Float get(View object) {
24387            return object.getY();
24388        }
24389    };
24390
24391    /**
24392     * A Property wrapper around the <code>z</code> functionality handled by the
24393     * {@link View#setZ(float)} and {@link View#getZ()} methods.
24394     */
24395    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
24396        @Override
24397        public void setValue(View object, float value) {
24398            object.setZ(value);
24399        }
24400
24401        @Override
24402        public Float get(View object) {
24403            return object.getZ();
24404        }
24405    };
24406
24407    /**
24408     * A Property wrapper around the <code>rotation</code> functionality handled by the
24409     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
24410     */
24411    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
24412        @Override
24413        public void setValue(View object, float value) {
24414            object.setRotation(value);
24415        }
24416
24417        @Override
24418        public Float get(View object) {
24419            return object.getRotation();
24420        }
24421    };
24422
24423    /**
24424     * A Property wrapper around the <code>rotationX</code> functionality handled by the
24425     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
24426     */
24427    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
24428        @Override
24429        public void setValue(View object, float value) {
24430            object.setRotationX(value);
24431        }
24432
24433        @Override
24434        public Float get(View object) {
24435            return object.getRotationX();
24436        }
24437    };
24438
24439    /**
24440     * A Property wrapper around the <code>rotationY</code> functionality handled by the
24441     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
24442     */
24443    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
24444        @Override
24445        public void setValue(View object, float value) {
24446            object.setRotationY(value);
24447        }
24448
24449        @Override
24450        public Float get(View object) {
24451            return object.getRotationY();
24452        }
24453    };
24454
24455    /**
24456     * A Property wrapper around the <code>scaleX</code> functionality handled by the
24457     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
24458     */
24459    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
24460        @Override
24461        public void setValue(View object, float value) {
24462            object.setScaleX(value);
24463        }
24464
24465        @Override
24466        public Float get(View object) {
24467            return object.getScaleX();
24468        }
24469    };
24470
24471    /**
24472     * A Property wrapper around the <code>scaleY</code> functionality handled by the
24473     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
24474     */
24475    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
24476        @Override
24477        public void setValue(View object, float value) {
24478            object.setScaleY(value);
24479        }
24480
24481        @Override
24482        public Float get(View object) {
24483            return object.getScaleY();
24484        }
24485    };
24486
24487    /**
24488     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
24489     * Each MeasureSpec represents a requirement for either the width or the height.
24490     * A MeasureSpec is comprised of a size and a mode. There are three possible
24491     * modes:
24492     * <dl>
24493     * <dt>UNSPECIFIED</dt>
24494     * <dd>
24495     * The parent has not imposed any constraint on the child. It can be whatever size
24496     * it wants.
24497     * </dd>
24498     *
24499     * <dt>EXACTLY</dt>
24500     * <dd>
24501     * The parent has determined an exact size for the child. The child is going to be
24502     * given those bounds regardless of how big it wants to be.
24503     * </dd>
24504     *
24505     * <dt>AT_MOST</dt>
24506     * <dd>
24507     * The child can be as large as it wants up to the specified size.
24508     * </dd>
24509     * </dl>
24510     *
24511     * MeasureSpecs are implemented as ints to reduce object allocation. This class
24512     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
24513     */
24514    public static class MeasureSpec {
24515        private static final int MODE_SHIFT = 30;
24516        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
24517
24518        /** @hide */
24519        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
24520        @Retention(RetentionPolicy.SOURCE)
24521        public @interface MeasureSpecMode {}
24522
24523        /**
24524         * Measure specification mode: The parent has not imposed any constraint
24525         * on the child. It can be whatever size it wants.
24526         */
24527        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
24528
24529        /**
24530         * Measure specification mode: The parent has determined an exact size
24531         * for the child. The child is going to be given those bounds regardless
24532         * of how big it wants to be.
24533         */
24534        public static final int EXACTLY     = 1 << MODE_SHIFT;
24535
24536        /**
24537         * Measure specification mode: The child can be as large as it wants up
24538         * to the specified size.
24539         */
24540        public static final int AT_MOST     = 2 << MODE_SHIFT;
24541
24542        /**
24543         * Creates a measure specification based on the supplied size and mode.
24544         *
24545         * The mode must always be one of the following:
24546         * <ul>
24547         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
24548         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
24549         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
24550         * </ul>
24551         *
24552         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
24553         * implementation was such that the order of arguments did not matter
24554         * and overflow in either value could impact the resulting MeasureSpec.
24555         * {@link android.widget.RelativeLayout} was affected by this bug.
24556         * Apps targeting API levels greater than 17 will get the fixed, more strict
24557         * behavior.</p>
24558         *
24559         * @param size the size of the measure specification
24560         * @param mode the mode of the measure specification
24561         * @return the measure specification based on size and mode
24562         */
24563        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
24564                                          @MeasureSpecMode int mode) {
24565            if (sUseBrokenMakeMeasureSpec) {
24566                return size + mode;
24567            } else {
24568                return (size & ~MODE_MASK) | (mode & MODE_MASK);
24569            }
24570        }
24571
24572        /**
24573         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
24574         * will automatically get a size of 0. Older apps expect this.
24575         *
24576         * @hide internal use only for compatibility with system widgets and older apps
24577         */
24578        public static int makeSafeMeasureSpec(int size, int mode) {
24579            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
24580                return 0;
24581            }
24582            return makeMeasureSpec(size, mode);
24583        }
24584
24585        /**
24586         * Extracts the mode from the supplied measure specification.
24587         *
24588         * @param measureSpec the measure specification to extract the mode from
24589         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
24590         *         {@link android.view.View.MeasureSpec#AT_MOST} or
24591         *         {@link android.view.View.MeasureSpec#EXACTLY}
24592         */
24593        @MeasureSpecMode
24594        public static int getMode(int measureSpec) {
24595            //noinspection ResourceType
24596            return (measureSpec & MODE_MASK);
24597        }
24598
24599        /**
24600         * Extracts the size from the supplied measure specification.
24601         *
24602         * @param measureSpec the measure specification to extract the size from
24603         * @return the size in pixels defined in the supplied measure specification
24604         */
24605        public static int getSize(int measureSpec) {
24606            return (measureSpec & ~MODE_MASK);
24607        }
24608
24609        static int adjust(int measureSpec, int delta) {
24610            final int mode = getMode(measureSpec);
24611            int size = getSize(measureSpec);
24612            if (mode == UNSPECIFIED) {
24613                // No need to adjust size for UNSPECIFIED mode.
24614                return makeMeasureSpec(size, UNSPECIFIED);
24615            }
24616            size += delta;
24617            if (size < 0) {
24618                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
24619                        ") spec: " + toString(measureSpec) + " delta: " + delta);
24620                size = 0;
24621            }
24622            return makeMeasureSpec(size, mode);
24623        }
24624
24625        /**
24626         * Returns a String representation of the specified measure
24627         * specification.
24628         *
24629         * @param measureSpec the measure specification to convert to a String
24630         * @return a String with the following format: "MeasureSpec: MODE SIZE"
24631         */
24632        public static String toString(int measureSpec) {
24633            int mode = getMode(measureSpec);
24634            int size = getSize(measureSpec);
24635
24636            StringBuilder sb = new StringBuilder("MeasureSpec: ");
24637
24638            if (mode == UNSPECIFIED)
24639                sb.append("UNSPECIFIED ");
24640            else if (mode == EXACTLY)
24641                sb.append("EXACTLY ");
24642            else if (mode == AT_MOST)
24643                sb.append("AT_MOST ");
24644            else
24645                sb.append(mode).append(" ");
24646
24647            sb.append(size);
24648            return sb.toString();
24649        }
24650    }
24651
24652    private final class CheckForLongPress implements Runnable {
24653        private int mOriginalWindowAttachCount;
24654        private float mX;
24655        private float mY;
24656        private boolean mOriginalPressedState;
24657
24658        @Override
24659        public void run() {
24660            if ((mOriginalPressedState == isPressed()) && (mParent != null)
24661                    && mOriginalWindowAttachCount == mWindowAttachCount) {
24662                if (performLongClick(mX, mY)) {
24663                    mHasPerformedLongPress = true;
24664                }
24665            }
24666        }
24667
24668        public void setAnchor(float x, float y) {
24669            mX = x;
24670            mY = y;
24671        }
24672
24673        public void rememberWindowAttachCount() {
24674            mOriginalWindowAttachCount = mWindowAttachCount;
24675        }
24676
24677        public void rememberPressedState() {
24678            mOriginalPressedState = isPressed();
24679        }
24680    }
24681
24682    private final class CheckForTap implements Runnable {
24683        public float x;
24684        public float y;
24685
24686        @Override
24687        public void run() {
24688            mPrivateFlags &= ~PFLAG_PREPRESSED;
24689            setPressed(true, x, y);
24690            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
24691        }
24692    }
24693
24694    private final class PerformClick implements Runnable {
24695        @Override
24696        public void run() {
24697            performClick();
24698        }
24699    }
24700
24701    /**
24702     * This method returns a ViewPropertyAnimator object, which can be used to animate
24703     * specific properties on this View.
24704     *
24705     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
24706     */
24707    public ViewPropertyAnimator animate() {
24708        if (mAnimator == null) {
24709            mAnimator = new ViewPropertyAnimator(this);
24710        }
24711        return mAnimator;
24712    }
24713
24714    /**
24715     * Sets the name of the View to be used to identify Views in Transitions.
24716     * Names should be unique in the View hierarchy.
24717     *
24718     * @param transitionName The name of the View to uniquely identify it for Transitions.
24719     */
24720    public final void setTransitionName(String transitionName) {
24721        mTransitionName = transitionName;
24722    }
24723
24724    /**
24725     * Returns the name of the View to be used to identify Views in Transitions.
24726     * Names should be unique in the View hierarchy.
24727     *
24728     * <p>This returns null if the View has not been given a name.</p>
24729     *
24730     * @return The name used of the View to be used to identify Views in Transitions or null
24731     * if no name has been given.
24732     */
24733    @ViewDebug.ExportedProperty
24734    public String getTransitionName() {
24735        return mTransitionName;
24736    }
24737
24738    /**
24739     * @hide
24740     */
24741    public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) {
24742        // Do nothing.
24743    }
24744
24745    /**
24746     * Interface definition for a callback to be invoked when a hardware key event is
24747     * dispatched to this view. The callback will be invoked before the key event is
24748     * given to the view. This is only useful for hardware keyboards; a software input
24749     * method has no obligation to trigger this listener.
24750     */
24751    public interface OnKeyListener {
24752        /**
24753         * Called when a hardware key is dispatched to a view. This allows listeners to
24754         * get a chance to respond before the target view.
24755         * <p>Key presses in software keyboards will generally NOT trigger this method,
24756         * although some may elect to do so in some situations. Do not assume a
24757         * software input method has to be key-based; even if it is, it may use key presses
24758         * in a different way than you expect, so there is no way to reliably catch soft
24759         * input key presses.
24760         *
24761         * @param v The view the key has been dispatched to.
24762         * @param keyCode The code for the physical key that was pressed
24763         * @param event The KeyEvent object containing full information about
24764         *        the event.
24765         * @return True if the listener has consumed the event, false otherwise.
24766         */
24767        boolean onKey(View v, int keyCode, KeyEvent event);
24768    }
24769
24770    /**
24771     * Interface definition for a callback to be invoked when a touch event is
24772     * dispatched to this view. The callback will be invoked before the touch
24773     * event is given to the view.
24774     */
24775    public interface OnTouchListener {
24776        /**
24777         * Called when a touch event is dispatched to a view. This allows listeners to
24778         * get a chance to respond before the target view.
24779         *
24780         * @param v The view the touch event has been dispatched to.
24781         * @param event The MotionEvent object containing full information about
24782         *        the event.
24783         * @return True if the listener has consumed the event, false otherwise.
24784         */
24785        boolean onTouch(View v, MotionEvent event);
24786    }
24787
24788    /**
24789     * Interface definition for a callback to be invoked when a hover event is
24790     * dispatched to this view. The callback will be invoked before the hover
24791     * event is given to the view.
24792     */
24793    public interface OnHoverListener {
24794        /**
24795         * Called when a hover event is dispatched to a view. This allows listeners to
24796         * get a chance to respond before the target view.
24797         *
24798         * @param v The view the hover event has been dispatched to.
24799         * @param event The MotionEvent object containing full information about
24800         *        the event.
24801         * @return True if the listener has consumed the event, false otherwise.
24802         */
24803        boolean onHover(View v, MotionEvent event);
24804    }
24805
24806    /**
24807     * Interface definition for a callback to be invoked when a generic motion event is
24808     * dispatched to this view. The callback will be invoked before the generic motion
24809     * event is given to the view.
24810     */
24811    public interface OnGenericMotionListener {
24812        /**
24813         * Called when a generic motion event is dispatched to a view. This allows listeners to
24814         * get a chance to respond before the target view.
24815         *
24816         * @param v The view the generic motion event has been dispatched to.
24817         * @param event The MotionEvent object containing full information about
24818         *        the event.
24819         * @return True if the listener has consumed the event, false otherwise.
24820         */
24821        boolean onGenericMotion(View v, MotionEvent event);
24822    }
24823
24824    /**
24825     * Interface definition for a callback to be invoked when a view has been clicked and held.
24826     */
24827    public interface OnLongClickListener {
24828        /**
24829         * Called when a view has been clicked and held.
24830         *
24831         * @param v The view that was clicked and held.
24832         *
24833         * @return true if the callback consumed the long click, false otherwise.
24834         */
24835        boolean onLongClick(View v);
24836    }
24837
24838    /**
24839     * Interface definition for a callback to be invoked when a drag is being dispatched
24840     * to this view.  The callback will be invoked before the hosting view's own
24841     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
24842     * onDrag(event) behavior, it should return 'false' from this callback.
24843     *
24844     * <div class="special reference">
24845     * <h3>Developer Guides</h3>
24846     * <p>For a guide to implementing drag and drop features, read the
24847     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
24848     * </div>
24849     */
24850    public interface OnDragListener {
24851        /**
24852         * Called when a drag event is dispatched to a view. This allows listeners
24853         * to get a chance to override base View behavior.
24854         *
24855         * @param v The View that received the drag event.
24856         * @param event The {@link android.view.DragEvent} object for the drag event.
24857         * @return {@code true} if the drag event was handled successfully, or {@code false}
24858         * if the drag event was not handled. Note that {@code false} will trigger the View
24859         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
24860         */
24861        boolean onDrag(View v, DragEvent event);
24862    }
24863
24864    /**
24865     * Interface definition for a callback to be invoked when the focus state of
24866     * a view changed.
24867     */
24868    public interface OnFocusChangeListener {
24869        /**
24870         * Called when the focus state of a view has changed.
24871         *
24872         * @param v The view whose state has changed.
24873         * @param hasFocus The new focus state of v.
24874         */
24875        void onFocusChange(View v, boolean hasFocus);
24876    }
24877
24878    /**
24879     * Interface definition for a callback to be invoked when a view is clicked.
24880     */
24881    public interface OnClickListener {
24882        /**
24883         * Called when a view has been clicked.
24884         *
24885         * @param v The view that was clicked.
24886         */
24887        void onClick(View v);
24888    }
24889
24890    /**
24891     * Interface definition for a callback to be invoked when a view is context clicked.
24892     */
24893    public interface OnContextClickListener {
24894        /**
24895         * Called when a view is context clicked.
24896         *
24897         * @param v The view that has been context clicked.
24898         * @return true if the callback consumed the context click, false otherwise.
24899         */
24900        boolean onContextClick(View v);
24901    }
24902
24903    /**
24904     * Interface definition for a callback to be invoked when the context menu
24905     * for this view is being built.
24906     */
24907    public interface OnCreateContextMenuListener {
24908        /**
24909         * Called when the context menu for this view is being built. It is not
24910         * safe to hold onto the menu after this method returns.
24911         *
24912         * @param menu The context menu that is being built
24913         * @param v The view for which the context menu is being built
24914         * @param menuInfo Extra information about the item for which the
24915         *            context menu should be shown. This information will vary
24916         *            depending on the class of v.
24917         */
24918        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
24919    }
24920
24921    /**
24922     * Interface definition for a callback to be invoked when the status bar changes
24923     * visibility.  This reports <strong>global</strong> changes to the system UI
24924     * state, not what the application is requesting.
24925     *
24926     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
24927     */
24928    public interface OnSystemUiVisibilityChangeListener {
24929        /**
24930         * Called when the status bar changes visibility because of a call to
24931         * {@link View#setSystemUiVisibility(int)}.
24932         *
24933         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
24934         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
24935         * This tells you the <strong>global</strong> state of these UI visibility
24936         * flags, not what your app is currently applying.
24937         */
24938        public void onSystemUiVisibilityChange(int visibility);
24939    }
24940
24941    /**
24942     * Interface definition for a callback to be invoked when this view is attached
24943     * or detached from its window.
24944     */
24945    public interface OnAttachStateChangeListener {
24946        /**
24947         * Called when the view is attached to a window.
24948         * @param v The view that was attached
24949         */
24950        public void onViewAttachedToWindow(View v);
24951        /**
24952         * Called when the view is detached from a window.
24953         * @param v The view that was detached
24954         */
24955        public void onViewDetachedFromWindow(View v);
24956    }
24957
24958    /**
24959     * Listener for applying window insets on a view in a custom way.
24960     *
24961     * <p>Apps may choose to implement this interface if they want to apply custom policy
24962     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
24963     * is set, its
24964     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
24965     * method will be called instead of the View's own
24966     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
24967     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
24968     * the View's normal behavior as part of its own.</p>
24969     */
24970    public interface OnApplyWindowInsetsListener {
24971        /**
24972         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
24973         * on a View, this listener method will be called instead of the view's own
24974         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
24975         *
24976         * @param v The view applying window insets
24977         * @param insets The insets to apply
24978         * @return The insets supplied, minus any insets that were consumed
24979         */
24980        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
24981    }
24982
24983    private final class UnsetPressedState implements Runnable {
24984        @Override
24985        public void run() {
24986            setPressed(false);
24987        }
24988    }
24989
24990    /**
24991     * When a view becomes invisible checks if autofill considers the view invisible too. This
24992     * happens after the regular removal operation to make sure the operation is finished by the
24993     * time this is called.
24994     */
24995    private static class VisibilityChangeForAutofillHandler extends Handler {
24996        private final AutofillManager mAfm;
24997        private final View mView;
24998
24999        private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm,
25000                @NonNull View view) {
25001            mAfm = afm;
25002            mView = view;
25003        }
25004
25005        @Override
25006        public void handleMessage(Message msg) {
25007            mAfm.notifyViewVisibilityChange(mView, mView.isShown());
25008        }
25009    }
25010
25011    /**
25012     * Base class for derived classes that want to save and restore their own
25013     * state in {@link android.view.View#onSaveInstanceState()}.
25014     */
25015    public static class BaseSavedState extends AbsSavedState {
25016        static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1;
25017        static final int IS_AUTOFILLED = 0b10;
25018        static final int AUTOFILL_ID = 0b100;
25019
25020        // Flags that describe what data in this state is valid
25021        int mSavedData;
25022        String mStartActivityRequestWhoSaved;
25023        boolean mIsAutofilled;
25024        int mAutofillViewId;
25025
25026        /**
25027         * Constructor used when reading from a parcel. Reads the state of the superclass.
25028         *
25029         * @param source parcel to read from
25030         */
25031        public BaseSavedState(Parcel source) {
25032            this(source, null);
25033        }
25034
25035        /**
25036         * Constructor used when reading from a parcel using a given class loader.
25037         * Reads the state of the superclass.
25038         *
25039         * @param source parcel to read from
25040         * @param loader ClassLoader to use for reading
25041         */
25042        public BaseSavedState(Parcel source, ClassLoader loader) {
25043            super(source, loader);
25044            mSavedData = source.readInt();
25045            mStartActivityRequestWhoSaved = source.readString();
25046            mIsAutofilled = source.readBoolean();
25047            mAutofillViewId = source.readInt();
25048        }
25049
25050        /**
25051         * Constructor called by derived classes when creating their SavedState objects
25052         *
25053         * @param superState The state of the superclass of this view
25054         */
25055        public BaseSavedState(Parcelable superState) {
25056            super(superState);
25057        }
25058
25059        @Override
25060        public void writeToParcel(Parcel out, int flags) {
25061            super.writeToParcel(out, flags);
25062
25063            out.writeInt(mSavedData);
25064            out.writeString(mStartActivityRequestWhoSaved);
25065            out.writeBoolean(mIsAutofilled);
25066            out.writeInt(mAutofillViewId);
25067        }
25068
25069        public static final Parcelable.Creator<BaseSavedState> CREATOR
25070                = new Parcelable.ClassLoaderCreator<BaseSavedState>() {
25071            @Override
25072            public BaseSavedState createFromParcel(Parcel in) {
25073                return new BaseSavedState(in);
25074            }
25075
25076            @Override
25077            public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) {
25078                return new BaseSavedState(in, loader);
25079            }
25080
25081            @Override
25082            public BaseSavedState[] newArray(int size) {
25083                return new BaseSavedState[size];
25084            }
25085        };
25086    }
25087
25088    /**
25089     * A set of information given to a view when it is attached to its parent
25090     * window.
25091     */
25092    final static class AttachInfo {
25093        interface Callbacks {
25094            void playSoundEffect(int effectId);
25095            boolean performHapticFeedback(int effectId, boolean always);
25096        }
25097
25098        /**
25099         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
25100         * to a Handler. This class contains the target (View) to invalidate and
25101         * the coordinates of the dirty rectangle.
25102         *
25103         * For performance purposes, this class also implements a pool of up to
25104         * POOL_LIMIT objects that get reused. This reduces memory allocations
25105         * whenever possible.
25106         */
25107        static class InvalidateInfo {
25108            private static final int POOL_LIMIT = 10;
25109
25110            private static final SynchronizedPool<InvalidateInfo> sPool =
25111                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
25112
25113            View target;
25114
25115            int left;
25116            int top;
25117            int right;
25118            int bottom;
25119
25120            public static InvalidateInfo obtain() {
25121                InvalidateInfo instance = sPool.acquire();
25122                return (instance != null) ? instance : new InvalidateInfo();
25123            }
25124
25125            public void recycle() {
25126                target = null;
25127                sPool.release(this);
25128            }
25129        }
25130
25131        final IWindowSession mSession;
25132
25133        final IWindow mWindow;
25134
25135        final IBinder mWindowToken;
25136
25137        Display mDisplay;
25138
25139        final Callbacks mRootCallbacks;
25140
25141        IWindowId mIWindowId;
25142        WindowId mWindowId;
25143
25144        /**
25145         * The top view of the hierarchy.
25146         */
25147        View mRootView;
25148
25149        IBinder mPanelParentWindowToken;
25150
25151        boolean mHardwareAccelerated;
25152        boolean mHardwareAccelerationRequested;
25153        ThreadedRenderer mThreadedRenderer;
25154        List<RenderNode> mPendingAnimatingRenderNodes;
25155
25156        /**
25157         * The state of the display to which the window is attached, as reported
25158         * by {@link Display#getState()}.  Note that the display state constants
25159         * declared by {@link Display} do not exactly line up with the screen state
25160         * constants declared by {@link View} (there are more display states than
25161         * screen states).
25162         */
25163        int mDisplayState = Display.STATE_UNKNOWN;
25164
25165        /**
25166         * Scale factor used by the compatibility mode
25167         */
25168        float mApplicationScale;
25169
25170        /**
25171         * Indicates whether the application is in compatibility mode
25172         */
25173        boolean mScalingRequired;
25174
25175        /**
25176         * Left position of this view's window
25177         */
25178        int mWindowLeft;
25179
25180        /**
25181         * Top position of this view's window
25182         */
25183        int mWindowTop;
25184
25185        /**
25186         * Indicates whether views need to use 32-bit drawing caches
25187         */
25188        boolean mUse32BitDrawingCache;
25189
25190        /**
25191         * For windows that are full-screen but using insets to layout inside
25192         * of the screen areas, these are the current insets to appear inside
25193         * the overscan area of the display.
25194         */
25195        final Rect mOverscanInsets = new Rect();
25196
25197        /**
25198         * For windows that are full-screen but using insets to layout inside
25199         * of the screen decorations, these are the current insets for the
25200         * content of the window.
25201         */
25202        final Rect mContentInsets = new Rect();
25203
25204        /**
25205         * For windows that are full-screen but using insets to layout inside
25206         * of the screen decorations, these are the current insets for the
25207         * actual visible parts of the window.
25208         */
25209        final Rect mVisibleInsets = new Rect();
25210
25211        /**
25212         * For windows that are full-screen but using insets to layout inside
25213         * of the screen decorations, these are the current insets for the
25214         * stable system windows.
25215         */
25216        final Rect mStableInsets = new Rect();
25217
25218        /**
25219         * For windows that include areas that are not covered by real surface these are the outsets
25220         * for real surface.
25221         */
25222        final Rect mOutsets = new Rect();
25223
25224        /**
25225         * In multi-window we force show the navigation bar. Because we don't want that the surface
25226         * size changes in this mode, we instead have a flag whether the navigation bar size should
25227         * always be consumed, so the app is treated like there is no virtual navigation bar at all.
25228         */
25229        boolean mAlwaysConsumeNavBar;
25230
25231        /**
25232         * The internal insets given by this window.  This value is
25233         * supplied by the client (through
25234         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
25235         * be given to the window manager when changed to be used in laying
25236         * out windows behind it.
25237         */
25238        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
25239                = new ViewTreeObserver.InternalInsetsInfo();
25240
25241        /**
25242         * Set to true when mGivenInternalInsets is non-empty.
25243         */
25244        boolean mHasNonEmptyGivenInternalInsets;
25245
25246        /**
25247         * All views in the window's hierarchy that serve as scroll containers,
25248         * used to determine if the window can be resized or must be panned
25249         * to adjust for a soft input area.
25250         */
25251        final ArrayList<View> mScrollContainers = new ArrayList<View>();
25252
25253        final KeyEvent.DispatcherState mKeyDispatchState
25254                = new KeyEvent.DispatcherState();
25255
25256        /**
25257         * Indicates whether the view's window currently has the focus.
25258         */
25259        boolean mHasWindowFocus;
25260
25261        /**
25262         * The current visibility of the window.
25263         */
25264        int mWindowVisibility;
25265
25266        /**
25267         * Indicates the time at which drawing started to occur.
25268         */
25269        long mDrawingTime;
25270
25271        /**
25272         * Indicates whether or not ignoring the DIRTY_MASK flags.
25273         */
25274        boolean mIgnoreDirtyState;
25275
25276        /**
25277         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
25278         * to avoid clearing that flag prematurely.
25279         */
25280        boolean mSetIgnoreDirtyState = false;
25281
25282        /**
25283         * Indicates whether the view's window is currently in touch mode.
25284         */
25285        boolean mInTouchMode;
25286
25287        /**
25288         * Indicates whether the view has requested unbuffered input dispatching for the current
25289         * event stream.
25290         */
25291        boolean mUnbufferedDispatchRequested;
25292
25293        /**
25294         * Indicates that ViewAncestor should trigger a global layout change
25295         * the next time it performs a traversal
25296         */
25297        boolean mRecomputeGlobalAttributes;
25298
25299        /**
25300         * Always report new attributes at next traversal.
25301         */
25302        boolean mForceReportNewAttributes;
25303
25304        /**
25305         * Set during a traveral if any views want to keep the screen on.
25306         */
25307        boolean mKeepScreenOn;
25308
25309        /**
25310         * Set during a traveral if the light center needs to be updated.
25311         */
25312        boolean mNeedsUpdateLightCenter;
25313
25314        /**
25315         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
25316         */
25317        int mSystemUiVisibility;
25318
25319        /**
25320         * Hack to force certain system UI visibility flags to be cleared.
25321         */
25322        int mDisabledSystemUiVisibility;
25323
25324        /**
25325         * Last global system UI visibility reported by the window manager.
25326         */
25327        int mGlobalSystemUiVisibility = -1;
25328
25329        /**
25330         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
25331         * attached.
25332         */
25333        boolean mHasSystemUiListeners;
25334
25335        /**
25336         * Set if the window has requested to extend into the overscan region
25337         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
25338         */
25339        boolean mOverscanRequested;
25340
25341        /**
25342         * Set if the visibility of any views has changed.
25343         */
25344        boolean mViewVisibilityChanged;
25345
25346        /**
25347         * Set to true if a view has been scrolled.
25348         */
25349        boolean mViewScrollChanged;
25350
25351        /**
25352         * Set to true if high contrast mode enabled
25353         */
25354        boolean mHighContrastText;
25355
25356        /**
25357         * Set to true if a pointer event is currently being handled.
25358         */
25359        boolean mHandlingPointerEvent;
25360
25361        /**
25362         * Global to the view hierarchy used as a temporary for dealing with
25363         * x/y points in the transparent region computations.
25364         */
25365        final int[] mTransparentLocation = new int[2];
25366
25367        /**
25368         * Global to the view hierarchy used as a temporary for dealing with
25369         * x/y points in the ViewGroup.invalidateChild implementation.
25370         */
25371        final int[] mInvalidateChildLocation = new int[2];
25372
25373        /**
25374         * Global to the view hierarchy used as a temporary for dealing with
25375         * computing absolute on-screen location.
25376         */
25377        final int[] mTmpLocation = new int[2];
25378
25379        /**
25380         * Global to the view hierarchy used as a temporary for dealing with
25381         * x/y location when view is transformed.
25382         */
25383        final float[] mTmpTransformLocation = new float[2];
25384
25385        /**
25386         * The view tree observer used to dispatch global events like
25387         * layout, pre-draw, touch mode change, etc.
25388         */
25389        final ViewTreeObserver mTreeObserver;
25390
25391        /**
25392         * A Canvas used by the view hierarchy to perform bitmap caching.
25393         */
25394        Canvas mCanvas;
25395
25396        /**
25397         * The view root impl.
25398         */
25399        final ViewRootImpl mViewRootImpl;
25400
25401        /**
25402         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
25403         * handler can be used to pump events in the UI events queue.
25404         */
25405        final Handler mHandler;
25406
25407        /**
25408         * Temporary for use in computing invalidate rectangles while
25409         * calling up the hierarchy.
25410         */
25411        final Rect mTmpInvalRect = new Rect();
25412
25413        /**
25414         * Temporary for use in computing hit areas with transformed views
25415         */
25416        final RectF mTmpTransformRect = new RectF();
25417
25418        /**
25419         * Temporary for use in computing hit areas with transformed views
25420         */
25421        final RectF mTmpTransformRect1 = new RectF();
25422
25423        /**
25424         * Temporary list of rectanges.
25425         */
25426        final List<RectF> mTmpRectList = new ArrayList<>();
25427
25428        /**
25429         * Temporary for use in transforming invalidation rect
25430         */
25431        final Matrix mTmpMatrix = new Matrix();
25432
25433        /**
25434         * Temporary for use in transforming invalidation rect
25435         */
25436        final Transformation mTmpTransformation = new Transformation();
25437
25438        /**
25439         * Temporary for use in querying outlines from OutlineProviders
25440         */
25441        final Outline mTmpOutline = new Outline();
25442
25443        /**
25444         * Temporary list for use in collecting focusable descendents of a view.
25445         */
25446        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
25447
25448        /**
25449         * The id of the window for accessibility purposes.
25450         */
25451        int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
25452
25453        /**
25454         * Flags related to accessibility processing.
25455         *
25456         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
25457         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
25458         */
25459        int mAccessibilityFetchFlags;
25460
25461        /**
25462         * The drawable for highlighting accessibility focus.
25463         */
25464        Drawable mAccessibilityFocusDrawable;
25465
25466        /**
25467         * The drawable for highlighting autofilled views.
25468         *
25469         * @see #isAutofilled()
25470         */
25471        Drawable mAutofilledDrawable;
25472
25473        /**
25474         * Show where the margins, bounds and layout bounds are for each view.
25475         */
25476        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
25477
25478        /**
25479         * Point used to compute visible regions.
25480         */
25481        final Point mPoint = new Point();
25482
25483        /**
25484         * Used to track which View originated a requestLayout() call, used when
25485         * requestLayout() is called during layout.
25486         */
25487        View mViewRequestingLayout;
25488
25489        /**
25490         * Used to track views that need (at least) a partial relayout at their current size
25491         * during the next traversal.
25492         */
25493        List<View> mPartialLayoutViews = new ArrayList<>();
25494
25495        /**
25496         * Swapped with mPartialLayoutViews during layout to avoid concurrent
25497         * modification. Lazily assigned during ViewRootImpl layout.
25498         */
25499        List<View> mEmptyPartialLayoutViews;
25500
25501        /**
25502         * Used to track the identity of the current drag operation.
25503         */
25504        IBinder mDragToken;
25505
25506        /**
25507         * The drag shadow surface for the current drag operation.
25508         */
25509        public Surface mDragSurface;
25510
25511
25512        /**
25513         * The view that currently has a tooltip displayed.
25514         */
25515        View mTooltipHost;
25516
25517        /**
25518         * Creates a new set of attachment information with the specified
25519         * events handler and thread.
25520         *
25521         * @param handler the events handler the view must use
25522         */
25523        AttachInfo(IWindowSession session, IWindow window, Display display,
25524                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
25525                Context context) {
25526            mSession = session;
25527            mWindow = window;
25528            mWindowToken = window.asBinder();
25529            mDisplay = display;
25530            mViewRootImpl = viewRootImpl;
25531            mHandler = handler;
25532            mRootCallbacks = effectPlayer;
25533            mTreeObserver = new ViewTreeObserver(context);
25534        }
25535    }
25536
25537    /**
25538     * <p>ScrollabilityCache holds various fields used by a View when scrolling
25539     * is supported. This avoids keeping too many unused fields in most
25540     * instances of View.</p>
25541     */
25542    private static class ScrollabilityCache implements Runnable {
25543
25544        /**
25545         * Scrollbars are not visible
25546         */
25547        public static final int OFF = 0;
25548
25549        /**
25550         * Scrollbars are visible
25551         */
25552        public static final int ON = 1;
25553
25554        /**
25555         * Scrollbars are fading away
25556         */
25557        public static final int FADING = 2;
25558
25559        public boolean fadeScrollBars;
25560
25561        public int fadingEdgeLength;
25562        public int scrollBarDefaultDelayBeforeFade;
25563        public int scrollBarFadeDuration;
25564
25565        public int scrollBarSize;
25566        public int scrollBarMinTouchTarget;
25567        public ScrollBarDrawable scrollBar;
25568        public float[] interpolatorValues;
25569        public View host;
25570
25571        public final Paint paint;
25572        public final Matrix matrix;
25573        public Shader shader;
25574
25575        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
25576
25577        private static final float[] OPAQUE = { 255 };
25578        private static final float[] TRANSPARENT = { 0.0f };
25579
25580        /**
25581         * When fading should start. This time moves into the future every time
25582         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
25583         */
25584        public long fadeStartTime;
25585
25586
25587        /**
25588         * The current state of the scrollbars: ON, OFF, or FADING
25589         */
25590        public int state = OFF;
25591
25592        private int mLastColor;
25593
25594        public final Rect mScrollBarBounds = new Rect();
25595        public final Rect mScrollBarTouchBounds = new Rect();
25596
25597        public static final int NOT_DRAGGING = 0;
25598        public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1;
25599        public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2;
25600        public int mScrollBarDraggingState = NOT_DRAGGING;
25601
25602        public float mScrollBarDraggingPos = 0;
25603
25604        public ScrollabilityCache(ViewConfiguration configuration, View host) {
25605            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
25606            scrollBarSize = configuration.getScaledScrollBarSize();
25607            scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget();
25608            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
25609            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
25610
25611            paint = new Paint();
25612            matrix = new Matrix();
25613            // use use a height of 1, and then wack the matrix each time we
25614            // actually use it.
25615            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25616            paint.setShader(shader);
25617            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25618
25619            this.host = host;
25620        }
25621
25622        public void setFadeColor(int color) {
25623            if (color != mLastColor) {
25624                mLastColor = color;
25625
25626                if (color != 0) {
25627                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
25628                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
25629                    paint.setShader(shader);
25630                    // Restore the default transfer mode (src_over)
25631                    paint.setXfermode(null);
25632                } else {
25633                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
25634                    paint.setShader(shader);
25635                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
25636                }
25637            }
25638        }
25639
25640        public void run() {
25641            long now = AnimationUtils.currentAnimationTimeMillis();
25642            if (now >= fadeStartTime) {
25643
25644                // the animation fades the scrollbars out by changing
25645                // the opacity (alpha) from fully opaque to fully
25646                // transparent
25647                int nextFrame = (int) now;
25648                int framesCount = 0;
25649
25650                Interpolator interpolator = scrollBarInterpolator;
25651
25652                // Start opaque
25653                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
25654
25655                // End transparent
25656                nextFrame += scrollBarFadeDuration;
25657                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
25658
25659                state = FADING;
25660
25661                // Kick off the fade animation
25662                host.invalidate(true);
25663            }
25664        }
25665    }
25666
25667    /**
25668     * Resuable callback for sending
25669     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
25670     */
25671    private class SendViewScrolledAccessibilityEvent implements Runnable {
25672        public volatile boolean mIsPending;
25673
25674        public void run() {
25675            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
25676            mIsPending = false;
25677        }
25678    }
25679
25680    /**
25681     * <p>
25682     * This class represents a delegate that can be registered in a {@link View}
25683     * to enhance accessibility support via composition rather via inheritance.
25684     * It is specifically targeted to widget developers that extend basic View
25685     * classes i.e. classes in package android.view, that would like their
25686     * applications to be backwards compatible.
25687     * </p>
25688     * <div class="special reference">
25689     * <h3>Developer Guides</h3>
25690     * <p>For more information about making applications accessible, read the
25691     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
25692     * developer guide.</p>
25693     * </div>
25694     * <p>
25695     * A scenario in which a developer would like to use an accessibility delegate
25696     * is overriding a method introduced in a later API version than the minimal API
25697     * version supported by the application. For example, the method
25698     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
25699     * in API version 4 when the accessibility APIs were first introduced. If a
25700     * developer would like his application to run on API version 4 devices (assuming
25701     * all other APIs used by the application are version 4 or lower) and take advantage
25702     * of this method, instead of overriding the method which would break the application's
25703     * backwards compatibility, he can override the corresponding method in this
25704     * delegate and register the delegate in the target View if the API version of
25705     * the system is high enough, i.e. the API version is the same as or higher than the API
25706     * version that introduced
25707     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
25708     * </p>
25709     * <p>
25710     * Here is an example implementation:
25711     * </p>
25712     * <code><pre><p>
25713     * if (Build.VERSION.SDK_INT >= 14) {
25714     *     // If the API version is equal of higher than the version in
25715     *     // which onInitializeAccessibilityNodeInfo was introduced we
25716     *     // register a delegate with a customized implementation.
25717     *     View view = findViewById(R.id.view_id);
25718     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
25719     *         public void onInitializeAccessibilityNodeInfo(View host,
25720     *                 AccessibilityNodeInfo info) {
25721     *             // Let the default implementation populate the info.
25722     *             super.onInitializeAccessibilityNodeInfo(host, info);
25723     *             // Set some other information.
25724     *             info.setEnabled(host.isEnabled());
25725     *         }
25726     *     });
25727     * }
25728     * </code></pre></p>
25729     * <p>
25730     * This delegate contains methods that correspond to the accessibility methods
25731     * in View. If a delegate has been specified the implementation in View hands
25732     * off handling to the corresponding method in this delegate. The default
25733     * implementation the delegate methods behaves exactly as the corresponding
25734     * method in View for the case of no accessibility delegate been set. Hence,
25735     * to customize the behavior of a View method, clients can override only the
25736     * corresponding delegate method without altering the behavior of the rest
25737     * accessibility related methods of the host view.
25738     * </p>
25739     * <p>
25740     * <strong>Note:</strong> On platform versions prior to
25741     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
25742     * views in the {@code android.widget.*} package are called <i>before</i>
25743     * host methods. This prevents certain properties such as class name from
25744     * being modified by overriding
25745     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
25746     * as any changes will be overwritten by the host class.
25747     * <p>
25748     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
25749     * methods are called <i>after</i> host methods, which all properties to be
25750     * modified without being overwritten by the host class.
25751     */
25752    public static class AccessibilityDelegate {
25753
25754        /**
25755         * Sends an accessibility event of the given type. If accessibility is not
25756         * enabled this method has no effect.
25757         * <p>
25758         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
25759         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
25760         * been set.
25761         * </p>
25762         *
25763         * @param host The View hosting the delegate.
25764         * @param eventType The type of the event to send.
25765         *
25766         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
25767         */
25768        public void sendAccessibilityEvent(View host, int eventType) {
25769            host.sendAccessibilityEventInternal(eventType);
25770        }
25771
25772        /**
25773         * Performs the specified accessibility action on the view. For
25774         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
25775         * <p>
25776         * The default implementation behaves as
25777         * {@link View#performAccessibilityAction(int, Bundle)
25778         *  View#performAccessibilityAction(int, Bundle)} for the case of
25779         *  no accessibility delegate been set.
25780         * </p>
25781         *
25782         * @param action The action to perform.
25783         * @return Whether the action was performed.
25784         *
25785         * @see View#performAccessibilityAction(int, Bundle)
25786         *      View#performAccessibilityAction(int, Bundle)
25787         */
25788        public boolean performAccessibilityAction(View host, int action, Bundle args) {
25789            return host.performAccessibilityActionInternal(action, args);
25790        }
25791
25792        /**
25793         * Sends an accessibility event. This method behaves exactly as
25794         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
25795         * empty {@link AccessibilityEvent} and does not perform a check whether
25796         * accessibility is enabled.
25797         * <p>
25798         * The default implementation behaves as
25799         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25800         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
25801         * the case of no accessibility delegate been set.
25802         * </p>
25803         *
25804         * @param host The View hosting the delegate.
25805         * @param event The event to send.
25806         *
25807         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25808         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
25809         */
25810        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
25811            host.sendAccessibilityEventUncheckedInternal(event);
25812        }
25813
25814        /**
25815         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
25816         * to its children for adding their text content to the event.
25817         * <p>
25818         * The default implementation behaves as
25819         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25820         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
25821         * the case of no accessibility delegate been set.
25822         * </p>
25823         *
25824         * @param host The View hosting the delegate.
25825         * @param event The event.
25826         * @return True if the event population was completed.
25827         *
25828         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25829         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
25830         */
25831        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25832            return host.dispatchPopulateAccessibilityEventInternal(event);
25833        }
25834
25835        /**
25836         * Gives a chance to the host View to populate the accessibility event with its
25837         * text content.
25838         * <p>
25839         * The default implementation behaves as
25840         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
25841         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
25842         * the case of no accessibility delegate been set.
25843         * </p>
25844         *
25845         * @param host The View hosting the delegate.
25846         * @param event The accessibility event which to populate.
25847         *
25848         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
25849         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
25850         */
25851        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
25852            host.onPopulateAccessibilityEventInternal(event);
25853        }
25854
25855        /**
25856         * Initializes an {@link AccessibilityEvent} with information about the
25857         * the host View which is the event source.
25858         * <p>
25859         * The default implementation behaves as
25860         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
25861         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
25862         * the case of no accessibility delegate been set.
25863         * </p>
25864         *
25865         * @param host The View hosting the delegate.
25866         * @param event The event to initialize.
25867         *
25868         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
25869         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
25870         */
25871        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
25872            host.onInitializeAccessibilityEventInternal(event);
25873        }
25874
25875        /**
25876         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
25877         * <p>
25878         * The default implementation behaves as
25879         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25880         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
25881         * the case of no accessibility delegate been set.
25882         * </p>
25883         *
25884         * @param host The View hosting the delegate.
25885         * @param info The instance to initialize.
25886         *
25887         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25888         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
25889         */
25890        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
25891            host.onInitializeAccessibilityNodeInfoInternal(info);
25892        }
25893
25894        /**
25895         * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the
25896         * additional data.
25897         * <p>
25898         * This method only needs to be implemented if the View offers to provide additional data.
25899         * </p>
25900         * <p>
25901         * The default implementation behaves as
25902         * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, int) for
25903         * the case where no accessibility delegate is set.
25904         * </p>
25905         *
25906         * @param host The View hosting the delegate. Never {@code null}.
25907         * @param info The info to which to add the extra data. Never {@code null}.
25908         * @param extraDataKey A key specifying the type of extra data to add to the info. The
25909         *                     extra data should be added to the {@link Bundle} returned by
25910         *                     the info's {@link AccessibilityNodeInfo#getExtras} method.  Never
25911         *                     {@code null}.
25912         * @param arguments A {@link Bundle} holding any arguments relevant for this request.
25913         *                  May be {@code null} if the if the service provided no arguments.
25914         *
25915         * @see AccessibilityNodeInfo#setExtraAvailableData
25916         */
25917        public void addExtraDataToAccessibilityNodeInfo(@NonNull View host,
25918                @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey,
25919                @Nullable Bundle arguments) {
25920            host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments);
25921        }
25922
25923        /**
25924         * Called when a child of the host View has requested sending an
25925         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
25926         * to augment the event.
25927         * <p>
25928         * The default implementation behaves as
25929         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25930         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
25931         * the case of no accessibility delegate been set.
25932         * </p>
25933         *
25934         * @param host The View hosting the delegate.
25935         * @param child The child which requests sending the event.
25936         * @param event The event to be sent.
25937         * @return True if the event should be sent
25938         *
25939         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25940         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
25941         */
25942        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
25943                AccessibilityEvent event) {
25944            return host.onRequestSendAccessibilityEventInternal(child, event);
25945        }
25946
25947        /**
25948         * Gets the provider for managing a virtual view hierarchy rooted at this View
25949         * and reported to {@link android.accessibilityservice.AccessibilityService}s
25950         * that explore the window content.
25951         * <p>
25952         * The default implementation behaves as
25953         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
25954         * the case of no accessibility delegate been set.
25955         * </p>
25956         *
25957         * @return The provider.
25958         *
25959         * @see AccessibilityNodeProvider
25960         */
25961        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
25962            return null;
25963        }
25964
25965        /**
25966         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
25967         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
25968         * This method is responsible for obtaining an accessibility node info from a
25969         * pool of reusable instances and calling
25970         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
25971         * view to initialize the former.
25972         * <p>
25973         * <strong>Note:</strong> The client is responsible for recycling the obtained
25974         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
25975         * creation.
25976         * </p>
25977         * <p>
25978         * The default implementation behaves as
25979         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
25980         * the case of no accessibility delegate been set.
25981         * </p>
25982         * @return A populated {@link AccessibilityNodeInfo}.
25983         *
25984         * @see AccessibilityNodeInfo
25985         *
25986         * @hide
25987         */
25988        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
25989            return host.createAccessibilityNodeInfoInternal();
25990        }
25991    }
25992
25993    private static class MatchIdPredicate implements Predicate<View> {
25994        public int mId;
25995
25996        @Override
25997        public boolean test(View view) {
25998            return (view.mID == mId);
25999        }
26000    }
26001
26002    private static class MatchLabelForPredicate implements Predicate<View> {
26003        private int mLabeledId;
26004
26005        @Override
26006        public boolean test(View view) {
26007            return (view.mLabelForId == mLabeledId);
26008        }
26009    }
26010
26011    private class SendViewStateChangedAccessibilityEvent implements Runnable {
26012        private int mChangeTypes = 0;
26013        private boolean mPosted;
26014        private boolean mPostedWithDelay;
26015        private long mLastEventTimeMillis;
26016
26017        @Override
26018        public void run() {
26019            mPosted = false;
26020            mPostedWithDelay = false;
26021            mLastEventTimeMillis = SystemClock.uptimeMillis();
26022            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
26023                final AccessibilityEvent event = AccessibilityEvent.obtain();
26024                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
26025                event.setContentChangeTypes(mChangeTypes);
26026                sendAccessibilityEventUnchecked(event);
26027            }
26028            mChangeTypes = 0;
26029        }
26030
26031        public void runOrPost(int changeType) {
26032            mChangeTypes |= changeType;
26033
26034            // If this is a live region or the child of a live region, collect
26035            // all events from this frame and send them on the next frame.
26036            if (inLiveRegion()) {
26037                // If we're already posted with a delay, remove that.
26038                if (mPostedWithDelay) {
26039                    removeCallbacks(this);
26040                    mPostedWithDelay = false;
26041                }
26042                // Only post if we're not already posted.
26043                if (!mPosted) {
26044                    post(this);
26045                    mPosted = true;
26046                }
26047                return;
26048            }
26049
26050            if (mPosted) {
26051                return;
26052            }
26053
26054            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
26055            final long minEventIntevalMillis =
26056                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
26057            if (timeSinceLastMillis >= minEventIntevalMillis) {
26058                removeCallbacks(this);
26059                run();
26060            } else {
26061                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
26062                mPostedWithDelay = true;
26063            }
26064        }
26065    }
26066
26067    private boolean inLiveRegion() {
26068        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
26069            return true;
26070        }
26071
26072        ViewParent parent = getParent();
26073        while (parent instanceof View) {
26074            if (((View) parent).getAccessibilityLiveRegion()
26075                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
26076                return true;
26077            }
26078            parent = parent.getParent();
26079        }
26080
26081        return false;
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